home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / comms / dis_pkt9.zip / DIS_PKT9.ASM next >
Assembly Source File  |  1991-11-02  |  68KB  |  2,295 lines

  1.     TITLE    DIS_PKT
  2.  
  3. ; DIS_PKT.ASM - Adapter provides Packet Driver v1.09 interface over NDIS.
  4. ; Version 1.07  18 May 1991  by Joe R. Doupnik, Utah State Univ.
  5. ; Version 1.08  9 Aug 1991 by Dan Lanciani, ddl@harvard.harvard.edu
  6. ; Version 1.09  3 Nov 1991 by Joe R. Doupnik, Utah State Univ.
  7. ; Copyright (C) 1988 - 1991 FTP Software, Inc.
  8. ;
  9. ; This unmodified source file and it's executable form may be used and
  10. ; redistributed freely.  The source may be modified, and the source or
  11. ; executable versions built from the modified source may be used and
  12. ; redistributed, provided that this notice and the copyright displayed by
  13. ; the exectuable remain intact, and provided that the executable displays
  14. ; an additional message indicating that it has been modified, and by whom.
  15. ;
  16. ; FTP Software Inc. releases this software "as is", with no express or
  17. ; implied warranty, including, but not limited to, the implied warranties
  18. ; of merchantability and fitness for a particular purpose.
  19. ;
  20. ; USE AT YOUR OWN RISK.
  21. ;
  22. ;
  23. ; To build, using Microsoft MASM 5 or later, LINK 3.64 or later, and EXE2BIN:
  24. ;
  25. ; masm dis_pkt;
  26. ; link dis_pkt;
  27. ; exe2bin dis_pkt.exe dis_pkt.dos
  28. ; del dis_pkt.exe
  29. ; del dis_pkt.obj
  30. ;
  31. ;
  32. ;What DIS_PKT.DOS does: It provides an Ethernet or a Token Ring Packet Driver
  33. ;interface to programs built to operate over Packet Drivers. It talks
  34. ;to NDIS (3Com/Microsoft) instead of to a lan board directly. It shares
  35. ;the board with NDIS users. We call this a "shim", sitting between the
  36. ;normal applications program (NetWare shells, TCP/IP, etc) and the more
  37. ;hardware specific portions (NDIS in this case).
  38. ;
  39. ;    Packet Driver flavored applications    NDIS flavored applications
  40. ;        ||                    ||
  41. ;        -------------                ||
  42. ;        |  DIS_PKT  |                ||
  43. ;        -------------                ||
  44. ;        ||                    ||
  45. ;        ------------------------------------------
  46. ;        |           main module              |
  47. ;        |   NDIS    ........................      |
  48. ;        |        board specific driver(s)      |
  49. ;        -------------------------------------------
  50. ;                  ||
  51. ;            --------------------------------
  52. ;            | Ethernet/Token Ring board(s)    |
  53. ;            --------------------------------
  54. ;                  ||
  55. ;        =================================== Ethernet/Token Ring wire
  56. ;        
  57. ;
  58. ;First sample PROTOCOL.INI file:
  59. ;
  60. ;[protocol manager]
  61. ;    drivername = PROTMAN$
  62. ;
  63. ;[pktdrv]            <-- name of this driver entry
  64. ;  drivername = pktdrv$        <-- formal driver name
  65. ;  bindings = wd8003xmac    <-- use your board's NDIS driver here
  66. ;  intvec = 0x60        <-- Packet Driver Int, 60h..7fh
  67. ;  chainvec = 0x66        <-- post-EOI processing interrupt, unused
  68. ;  novell = y            <-- Optional, if present and y(es) then
  69. ;                    convert between old Novell 802.3 pkts
  70. ;                    on the wire and Type 8137 for the app.
  71. ;                    Omitting this line or using any other
  72. ;                    response turns off the conversion; 
  73. ;                    default is no conversion.
  74. ;
  75. ;[attiso]
  76. ;  drivername = ATTISO$        <-- Another NDIS client
  77. ;  bindings = wd8003xmac    <-- bound to the same harware driver
  78. ;  nsess = 5
  79. ;  ncmds = 14
  80. ;  use_emm = n
  81. ;
  82. ;Western Digital EtherCard PLUS Family Adapter    <-- Ethernet board
  83. ;[wd8003xmac]                    <-- its ndis driver
  84. ;    drivername = MACWD$
  85. ;    irq = 7
  86. ;    ramaddress = 0xCA00
  87. ;    iobase = 0x280
  88. ;    receivebufsize = 1536    <-- make this a full Ethernet pkt
  89. ;
  90. ;
  91. ;
  92. ;
  93. ;Sample section of CONFIG.SYS (StarGROUP material is not required):
  94. ;
  95. ;device=c:\lanman\protman.sys /i:c:\lanman    <-- must be first
  96. ;device=c:\lanman\macwd.dos            <-- WD8003E driver
  97. ;device=c:\lanman\dis_pkt.dos            <-- Pkt Driver (this program)
  98. ;device=c:\lanman.dos\drivers\attload.dos /Y    <-- StarGROUP NDIS 
  99. ;device=c:\lanman.dos\drivers\attiso\attiso.dos    <-- StarGROUP NDIS
  100. ;device=c:\qemm\loadhi.sys /r:1 e:\pctcp\ifcust.sys  <-- PC/TCP stuff
  101. ;device=c:\qemm\loadhi.sys /r:4 e:\pctcp\ipcust.sys  <-- etc
  102. ;
  103. ;
  104. ; A second, more elaborate example, with names easier to type. We start with
  105. ;file PROTOCOL.INI. Note that semicolons start comment lines.
  106. ;
  107. ;; This is a sample protocol.ini file listing three Ethernet boards:
  108. ;;    attcsma.dos is an AT&T StarLAN 10 EN100
  109. ;;    elnkii.dos  is a 3Com 3C503
  110. ;;    wd8003.dos  is a Western Digital WD8003E
  111. ;; Only one board will be selected but the other two are present.
  112. ;
  113. ;[protocol manager]
  114. ;    drivername = PROTMAN$
  115. ;
  116. ;; Packet Driver protocol users tie in here
  117. ;[pktdrv]
  118. ;    drivername = pktdrv$
  119. ;    bindings = attcsma
  120. ;;    bindings= elnkii
  121. ;;    bindings = wd8003
  122. ;    intvec = 0x60
  123. ;;    chainvec = 0x66
  124. ;    novell = no        ; do not convert packet types this time
  125. ;
  126. ;; AT&T StarGROUP protocol stack ties in here via name ATTISO$
  127. ;[attiso]
  128. ;    drivername = ATTISO$
  129. ;    bindings = attcsma
  130. ;;    bindings = elnkii
  131. ;;    bindings = wd8003
  132. ;    nsess = 5
  133. ;    ncmds = 14
  134. ;    use_emm = n
  135. ;
  136. ;;Western Digital EtherCard PLUS Family Adapter, WD8003E in this case
  137. ;[wd8003]
  138. ;    drivername = MACWD$
  139. ;    irq = 7
  140. ;    ramaddress = 0xCA00
  141. ;    iobase = 0x280
  142. ;    receivebufsize = 1536
  143. ;;    maxtransmits = 6
  144. ;;    receivebuffers = 6
  145. ;;    receivechains = 6
  146. ;
  147. ;; 3Com Etherlink II, 3C503
  148. ;[elnkii]
  149. ;    drivername = ELNKII$
  150. ;    ioaddress = 0x350
  151. ;    interrupt = 5
  152. ;    transceiver = onboard
  153. ;    maxtransmits = 12
  154. ;    xmitbufs = 1
  155. ;
  156. ;; AT&T StarLAN 10 EN100
  157. ;[attcsma]
  158. ;    drivername = ATTCSMA$
  159. ;    board_type = 2
  160. ;    irq = 2
  161. ;    ioaddr = 0x360
  162. ;    daram = 0xD000
  163. ;
  164. ;; End of file protocol.ini
  165. ;
  166. ;Fragment of config.sys for the second example. Note three .dos board drivers.
  167. ;
  168. ;device=c:\system\ramdrive.sys 1024 512 128 /E
  169. ;device=c:\lanman\protman.sys /i:c:\lanman.dos\drivers\star10en
  170. ;device=c:\lanman\attcsma.dos
  171. ;device=c:\lanman\elnkii.sys
  172. ;device=c:\lanman\macwd.dos
  173. ;device=c:\lanman\dis_pkt.dos
  174. ;device=c:\lanman.dos\drivers\attload.dos /Y
  175. ;device=c:\lanman.dos\drivers\attiso\attiso.dos
  176. ;device=c:\qemm\loadhi.sys /r:1 e:\pctcp\ifcust.sys
  177. ;device=c:\qemm\loadhi.sys /r:4 e:\pctcp\ipcust.sys
  178. ;device=c:\qemm\loadhi.sys /r:4 c:\netdev.sys
  179. ;shell=c:\command.com  /p /e:800
  180. ;
  181. ;It seems to be necessary to run NETBIND.EXE to get all this to be active.
  182. ;
  183.  
  184. ; Edit History
  185. ; 06-Jul-89    WJR    Changed interface flags in LDT to 2 per Norsk Data
  186. ;             (may make vector binding work). Changed receive to
  187. ;             allocate buffer for frame size instead of lookahead
  188. ;             value. (This will fail miserably if the frame size
  189. ;             is unknown at upcall time; such is life.) Changed
  190. ;             SetPacketFilter to use module ID instead of dummy.
  191. ; 11-Sep-89    jbvb    Clean up, add 1.09 functionality.
  192. ; 12-Sep-89    jbvb    Don't do interrupt if vector contents are 0.
  193. ; 14-Sep-89     wjr    Changed frame_rejected to frame_not_recognized to make
  194. ;             vectored operation work.  Changed send_pkt to use
  195. ;             drv_cct.mod_id. Tried using 0 as protocol id in open
  196. ;             adapter call.  Changed device name to pktdrv$,
  197. ;             flushed open adapter not supported message.
  198. ; 15-Sep-89    wjr    Changed open adapter back to CS since 0 broke it.
  199. ; 24-Oct-89    wjr    Changed FRAME_NOT_RECOGNIZED from 4 to 3
  200. ; 07-Feb-90    wjr    Added push and pop SI to rcv_chn & rcv_lah.
  201. ; 02-Apr-90    wjr    Fixed xmt_chn to properly check for request queued
  202. ; 03-Apr-90    wjr    Given changed TCP, treat REQUEST_QUEUED as success.
  203. ; 06-Apr-90    jbvb    Update patch level to 2.
  204. ; 23-Apr-90    jbvb    Don't trash BP, free init code, fix comments.
  205. ; 25-Apr-90    jbvb    Support "extended" calls: get/set_rcv_mode,
  206. ;             get_statistics will suffice for LW.
  207. ; 26-Apr-90    jbvb    Support "match all" on typelen == 0.
  208. ; 05-Jun-90    jbvb    Fix stack bug in "match all" handling in access_type,
  209. ;             pass valid CX on 2nd receiver() upcall, version 5.
  210. ; 13-Jun-90    jbvb    Write basic set_address() code, but comment it out
  211. ;             because NDIS may require a CloseAdapter first in
  212. ;             order for it to work.  Not worth it to me.
  213. ; 27-Jul-90    jbvb    Copyright, build instructions, release v1.05.
  214. ; 24-Mar-91    jrd    Rewrite great chunks to straighen out stack and DS
  215. ;            addressing. This now works with Novell IPX/NETn
  216. ;            and Netwatch (together as a matter of fact) and
  217. ;            with PC/TCP from FTP Inc. Version to 1.06.
  218. ;            Joe R. Doupnik,    jrd@cc.usu.edu, Utah State Univ.
  219. ; 30-Mar-91    jrd    Allow 10 byte TYPE idents to pick out packets,
  220. ;            more cleanups, more needed. Promiscuous mode put last.
  221. ;            Allow 20 handles. Works fine with (NetWare+PC/TCP+
  222. ;            Netwatch) Pkt Drvr + Lan Man going simulanteously.
  223. ;            Works with Clarkson issued Packet Driver utilities.
  224. ; 18-May-91    jrd    Add filtering of packet addresses if running in
  225. ;            promiscuous mode, add get current Ethernet address
  226. ;            function to aid filtering, add receive mode indicator
  227. ;            for each handle, correct error in snd_def initing.
  228. ;            Correct problem with receive lookahead addressing.
  229. ;            Compensate for 3Com drivers not preserving regs.
  230. ;            Bump up NDIS tables to v2. Dis_pkt version to 1.07.
  231. ; 09-Aug-91    ddl    802.5, 802.3 support; default binding; overwrite fix
  232. ; 03-Nov-91    jrd    Add keyword NOVELL to PROTOCOL.INI to convert between
  233. ;            old Novell 802.3 packets on the wire to 8137 for the
  234. ;            applications program. Convert if the line is present
  235. ;            and the value is y(es). Small cleanups.
  236.     PAGE ,80
  237.  
  238. EOL    EQU    <13, 10, '$'>
  239. LF    =    10
  240. CR    =    13
  241. EOS    =    '$'
  242. DOS    equ    21h
  243. prstr    equ    9
  244. fopen    equ    3dh
  245. fclose    equ    3eh
  246. ioctl    equ    44h
  247.  
  248. MSG    MACRO    TEXT
  249.     PUSH    DX            ;; save DX across call
  250.     push    ax
  251.     push    ds
  252.     mov    ax,cs
  253.     mov    ds,ax
  254.     MOV    DX,OFFSET TEXT        ;; point to message
  255.     mov    ah,prstr        ; display dollar terinated string
  256.     int    dos
  257.     pop    ds
  258.     pop    ax
  259.     POP    DX
  260.     ENDM
  261.  
  262. ; DOS request header offsets
  263.  
  264. command    =    2
  265. status    =    3
  266. bpb    =    18
  267. end_off    =    14
  268. end_seg =    16
  269.  
  270. ; NDIS General Request codes
  271.  
  272. INIT_DIAG    equ    1
  273. READ_ERR_LOG    equ    2
  274. SET_STA_ADDR    equ    3
  275. OPEN_ADAPTER    equ    4
  276. CLOSE_ADAPTER    equ    5
  277. RESET_MAC    equ    6
  278. SET_PKT_FLT    equ    7
  279. ADD_MULT_ADDR    equ    8
  280. DEL_MULT_ADDR    equ    9
  281. UPDATE_STATS    equ    10
  282. CLEAR_STATS    equ    11
  283. INTERRUPT_ME    equ    12
  284. SET_FUNC_ADDR    equ    13
  285. SET_LOOKAHEAD    equ    14
  286.  
  287. ADDR_NONE    EQU    0    ; NDIS Receiver modes: disabled
  288. ADDR_MULT    EQU    1    ; Receive packets for my address & multicast
  289. ADDR_BRD    EQU    2    ; Receive broadcast packets
  290. ADDR_PROM    EQU    4    ; Receive all packets (promiscuous mode)
  291. ADDR_SRCRT    EQU    8    ; Receive all source-routed packets
  292.  
  293. ; Protocol to MAC return codes
  294.  
  295. SUCCESS            EQU    0
  296. REQUEST_QUEUED        EQU    2
  297. FRAME_NOT_RECOGNIZED    EQU    3
  298. NOT_SUPPORTED        EQU    9
  299. GENERAL_FAILURE        EQU    0FFH
  300.  
  301. ; NDIS-related structure definitions
  302.  
  303. cct_def    struc
  304.     dw    64        ; Size of common characteristics table (cct)
  305.     dw    0        ; Level of cct (zero this version)
  306.     dw    0        ; Level of service-specific subtables
  307.     db    2        ; Major module version (2 BCD digits)
  308.     db    0        ; Minor module version (2 BCD digits)
  309.     dd    2        ; Module function flags
  310.     db    'PKTDRV$', 9 dup (0) ; Module name, 16 byte ASCIIZ format
  311.     db    4        ; Protocol level at upper boundary of module
  312.     db    0        ; type of interface at upper module boundary
  313.     db    1        ; protocol level at lower boundary of module
  314.     db    1        ; type of interface at lower module boundary
  315. mod_id    dw    -1        ; module ID filled in by Protocol Manager
  316. mod_ds    dw    0        ; module DS
  317. system    dd    0        ; system request dispatch entry point
  318. sscp    dd    0        ; pointer to service-specific characteristics
  319. sssp    dd    0        ; pointer to service-specific status
  320. udtp    dd    0        ; pointer to upper dispatch table
  321. ldtp    dd    0        ; pointer to lower dispatch table
  322.     dd    0        ; reserved (must be NULL)
  323.     dd    0        ; reserved (must be NULL)
  324. cct_def    ends
  325.  
  326. ssc_def    struc
  327.     dw    94        ; length of MAC service-specific 
  328.                 ; characteristics table (ssc)
  329. mtype    db    16 dup (0)    ; type name of MAC, ASCIIZ format
  330.     dw    0        ; length of station addresses in bytes
  331.     db    16 dup (0)    ; permanent station address
  332. cur_add    db    16 dup (0)    ; current station address
  333.     dd    0        ; current functional address of adapter
  334.     dd    0        ; multicast address list
  335.     dd    0        ; link speed
  336. svc_1    dw    0        ; service flags
  337. svc_2    dw    0        ; service flags
  338. maxfram    dw    0        ; max frame size both sent and recv
  339.     dd    0        ; total transmission buffer cap in driver
  340.     dw    0        ; transmission buffer allocation block size
  341.     dd    0        ; total reception buffer cap in driver
  342.     dw    0        ; reception buffer allocation block size
  343.     db    3 dup (0)    ; IEEE vendor code (OUI)
  344.     db    0        ; vendor adapter code
  345.     dd    0        ; vendor adapter description pointer
  346.     dw    0        ; IRQ of adapter (NDIS v2)
  347.     dw    0        ; transmit queue depth (NDIS v2)
  348. ssc_def    ends
  349.  
  350. sss_def    struc
  351.     dw    0        ; length of status table
  352.     dd    0        ; date/time of last diagnostics 
  353.     dd    0        ; MAC status
  354.     dw    0        ; current packet filter
  355.     dd    0        ; pointer to media specific statistics table
  356.     dd    0        ; date/time of last ClearStatistics call
  357. r_tot    dd    0        ; total frames received
  358. r_crc    dd    0        ; frames with CRC error
  359. rb_tot    dd    0        ; total bytes received
  360. r_drop    dd    0        ; frames discarded - no buffer space
  361. r_mult    dd    0        ; multicast frames received
  362. r_bro    dd    0        ; broadcast frames received
  363. r_err    dd    0        ; frames received with errors
  364. r_big    dd    0        ; frames exceeding maximum size
  365. r_runt    dd    0        ; frames smaller than minimum size
  366. rb_mul    dd    0        ; multicast bytes received
  367. rb_bro    dd    0        ; broadcast bytes received
  368. r_hwer    dd    0        ; frames discarded - hardware error
  369. x_tot    dd    0        ; total frames transmitted
  370. xb_tot    dd    0        ; total bytes transmitted
  371. x_mul    dd    0        ; multicast frames transmitted
  372. x_bro    dd    0        ; broadcast frames transmitted
  373. xb_bro    dd    0        ; broadcast bytes transmitted
  374. xb_mul    dd    0        ; multicast bytes transmitted
  375. x_tmo    dd    0        ; frames not transmitted - time-out
  376. x_hwer    dd    0        ; frames not transmitted - hardware error
  377. sss_def    ends
  378.  
  379. udt_def    struc            ; upper dispatch table
  380.     dd    0        ; back pointer to cct
  381. reqadd    dd    0        ; request address
  382. xchain    dd    0        ; TransmitChain address
  383.     dd    0        ; TransferData address
  384.     dd    0        ; ReceiveRelease address
  385. indon    dd    0        ; IndicationOn address
  386. indoff    dd    0        ; IndicationOff address
  387. udt_def    ends
  388.  
  389. ldt_def    struc            ; lower dispatch table
  390.     dd    0        ; back pointer to cct
  391.     dd    2        ; interface flags (2 means something)
  392.     dd    0        ; RequestConfirm address
  393.         dd    0        ; TransmitConfirm address
  394.        dd    0        ; ReceiveLookahead indication address
  395.     dd    0        ; IndicationComplete address
  396.     dd    0        ; ReceiveChain indication address
  397.     dd    0        ; status indication address
  398. ldt_def    ends
  399.  
  400. snd_def    struc            ; transmit buffer descriptor
  401.     dw    0        ; byte count of immediate data (always 0)
  402.     dd    0        ; address of immediate data
  403.     dw    1        ; count of data blocks (always 1)
  404.     db    0        ; pointer type (0 == physical)
  405.     db    0        ; reserved
  406. snd_len    dw    0        ; number of bytes to send
  407. snd_off    dw    0        ; offset of data to send
  408. snd_seg    dw    0        ; segment of data to send
  409. snd_def    ends
  410.  
  411. rcv_def    struc        ; receive buffer descriptor
  412.     dw    1        ; count of data blocks (always 1)
  413.     db    0        ; pointer type (0 == physical)
  414.     db    0        ; reserved
  415. rcv_len    dw    0        ; number of bytes to get
  416. rcv_off    dw    0        ; offset of data to get
  417. rcv_seg    dw    0        ; segment of data to get
  418. rcv_def    ends
  419.  
  420. req_def    struc        ; Request block - Protocol Manager primitives
  421. req_opc    dw    0        ; opcode for PM request
  422. req_sta    dw    0        ; status returned from request
  423. req_of1    dw    0        ; first parameter pointer
  424. req_sg1    dw    0
  425. req_of2    dw    0        ; second parameter pointer
  426. req_sg2    dw    0
  427. req_prm    dw    0        ; parameter word
  428. req_def    ends
  429.  
  430. bnd_def    struc            ; binding list 
  431. bnd_cnt    dw    1        ; number of MACs to bind to -- 0 or 1
  432. bnd_nam    db    16 dup (0)    ; name of module to bind to
  433. bnd_def    ends
  434.  
  435.  
  436.     SUBTTL    Resident Data Area
  437.     PAGE
  438.  
  439. CSEG    SEGMENT PARA PUBLIC 'CODE'
  440.     assume    cs:CSEG, ds:CSEG, es:nothing
  441.  
  442. ; DEVICE HEADER - must be at offset zero within device driver
  443.     DD    -1        ; becomes pointer to next device header
  444.     DW    8000H        ; attribute (char device)
  445.     DW    OFFSET strat    ; pointer to device strategy routine
  446.     DW    OFFSET intr    ; pointer to device interrupt handler
  447.     DB    "PKTDRV$ "    ; device driver name
  448. ; END OF DEVICE HEADER
  449.  
  450. mac_cctp    dd    0    ; address of MAC's cct table
  451. mac_ds        dw    0    ; DS register for MAC
  452. rtn_cod        dw    0    ; Save NDIS return code here
  453.  
  454. drv_cct        cct_def    <>    ; Common Characteristics Table
  455. drv_ldt        ldt_def    <>    ; Lower Dispatch Table
  456. drv_snd        snd_def    <>    ; Argument blocks for NDIS TransmitChain,
  457. drv_rcv        rcv_def    <>    ;  TransferData,
  458. drv_bnd        bnd_def    <>    ;  and Bind (via DOS IOCTL)
  459. drv_req        req_def    <>    ; Argument block for general NDIS requests
  460. TransmitChain    dd    0        ; MAC entry point to send packet
  461. TransferData    dd    0        ; MAC entry point for data copy
  462. Request        dd    0        ; MAC entry point for requests
  463. ReceiveRelease    dd    0        ; MAC entry point (???not used???)
  464. IndicationOn    dd    0        ; MAC entries to control Indications
  465. IndicationOff    dd    0        ;  (upcalls) from NDIS
  466. req_con_flg    dw    REQUEST_QUEUED    ; Completion status from NDIS upcall
  467.  
  468. init_flg    db    0        ; Non-zero if we've been initialized
  469. address        db    16 dup (0)    ; Current address from MAC
  470. bytcnt        dw    0        ; Bytes copied by TransferData
  471. xmt_cmp        dw    SUCCESS        ; TransmitChain result
  472. open_adap    dw    0        ; OpenAdapter & SetPacketFilter result
  473.  
  474. ; Request Header (RH) address, saved here by "strategy" routine
  475.  
  476. req_hdr        LABEL    DWORD
  477. req_off        dw    0
  478. req_seg        dw    0
  479.  
  480. ; Save the request header for use by the interrupt routine
  481.  
  482. strat    PROC    FAR
  483.     mov    word ptr cs:req_off,bx    ; offset
  484.     mov    word ptr cs:req_seg,es    ; segment
  485.     ret
  486. strat    ENDP
  487.  
  488.     EVEN                    ; Get into word alignment
  489.  
  490. ;;
  491. ;; Data for Packet Driver
  492. ;;
  493. BAD_HANDLE    EQU 1    ; invalid handle number
  494. NO_CLASS    EQU 2    ; no interfaces of this class found
  495. NO_TYPE        EQU 3    ; no interfaces of specified type found
  496. NO_NUMBER    EQU 4    ; no interfaces of specified number found
  497. BAD_TYPE    EQU 5    ; bad packet type specified
  498. NO_MULTICAST    EQU 6    ; this interface does not support multicast
  499. CANT_TERMINATE    EQU 7    ; this packet driver cannot terminate
  500. BAD_MODE    EQU 8    ; an invalid receiver mode was specified
  501. NO_SPACE    EQU 9    ; operation failed because of insufficient space
  502. TYPE_INUSE    EQU 10    ; type had previously been accessed and not released
  503. BAD_COMMAND    EQU 11    ; the command was out of range or not implemented
  504. CANT_SEND    EQU 12    ; the packet couldn't be sent (usually hardware error)
  505. CANT_SET    EQU 13    ; The hardware address couldn't be changed
  506. BAD_ADDRESS    EQU 14    ; Hardware address has bad length or format
  507. CANT_RESET    EQU 15    ; Couldn't reset interface (more than 1 handle open)
  508.  
  509. PD_LEVEL    EQU    6    ; Implementation level (basic, high perf, ext)
  510. ANY_TYPE    EQU    0FFFFh    ; Matches any if_type
  511. ETHERADDR_LEN    EQU    6    ; Length of an Ethernet address
  512. ETHERTYPE_LEN    EQU    2    ; Length of Ethertypes
  513. ETHERTYPE_NONE    EQU    0    ; Ethertypes of 0 mean not defined
  514.  
  515. ; The connection arrays: types, and corresponding upcalls
  516.  
  517. PD_MAX_CONNS    EQU    20    ; The maximum number of handles/Types that can
  518.                 ;  be registered at one time
  519. MAX_P_LEN    equ    10    ; max length of TYPE matching field, bytes
  520.  
  521. per_handle    struc            ; Packet Driver HANDLE structure
  522. pd_conn_used    db    0        ; non-zero if this handle is in use
  523. pd_conn_type    db    MAX_P_LEN dup(0) ; associated packet type
  524. pd_conn_type_len dw    0        ; associated packet type length
  525. pd_conn_rmode    dw    3        ; receive mode for this handle
  526. pd_conn_rcvr    dd    0        ; receiver handler address
  527. pd_conn_class    db    0        ; interface class
  528. per_handle    ends
  529.  
  530. handles        per_handle PD_MAX_CONNS dup(<>)
  531. end_handles    label    byte
  532.  
  533. novell        db    0        ; if non-zero convert between old
  534.                     ; Novell 802.3 interior to Type 8137
  535.                     ; Caller used 8137, wire gets 802.3
  536.  
  537. ; Because some NDIS drivers can't support multiple calls to TransferData
  538. ; for a single reception, we only allow one handle (by implication, the last),
  539. ; to be in "match all" mode at a given time, but we do allow other handles
  540. ; to be open at the same time.
  541.  
  542. if_class    DB    1    ; Class 1 is Ethernet
  543. if_type        DW    57    ; NDIS to Packet Driver adapter
  544. pd_version    DW    9    ; Version
  545. conn_in_use    DW    0    ; Number of handles open
  546. pd_vector    DW    -1    ; Packet Driver vector to serve on
  547. pd_rcv_mode    DW    3    ; Default to rcv mode 3 (normal/bcast)
  548. pd_name        DB    "MAC/DIS converter", 0
  549. pd_recvall    db    0    ; non-zero if Promiscuous mode is active
  550. off        dw    12    ; offset to match bytes
  551. aoff        dw    0    ; offset to addresses
  552.  
  553. ; Table re-maps (badly) NDIS modes to Packet Driver modes (in parentheses)
  554. ndis_mode    db  0    ; No packets (0 == illegal)
  555.         db  0    ; No packets (1 == receiver off)
  556.         db  1    ; Directed | Multicast (2 should be directed only)
  557.         db  3    ; Directed | Multicast | Broadcast
  558.             ; (3 should be directed | broadcast)
  559.         db  3    ; Directed | limited Multicast | Broadcast
  560.             ; (4 == directed | broadcast | limited multicast)
  561.         db  3    ; Directed | limited Multicast | Broadcast
  562.             ; (5 should be directed | broadcast | all multicast)
  563.         db  4    ; Promiscuous (6 == match all)
  564.         
  565. EVEN    ; Get into word alignment
  566.  
  567. ; struct param; Pointer to this returned by get_parameters()
  568.  
  569. pd_param  db    1        ; Major revision = 1
  570.       db    9        ; Minor revision = 9
  571.       db    14        ; Length of this structure = 14
  572.       db    ETHERADDR_LEN    ; MAC addr length
  573. mtu      dw    1514        ; MAC packet length
  574.       dw    0        ; No multicast support
  575.       dw    0        ; No promises re: back-to-back receives
  576.       dw    0        ; No promises re: back-to-back transmits
  577. param_int dw    0        ; Default to no interrupt on EOI
  578.  
  579. ; Pointer to this returned by get_statistics
  580.  
  581. pd_statistics struc
  582. pkt_in        dd    0    ; Total packets in
  583. pkt_out        dd    0    ; Total packets out
  584. bytes_in    dd    0    ; Total bytes received
  585. bytes_out    dd    0    ; Total bytes sent
  586. errs_in        dd    0    ; Total transmit errors
  587. errs_out    dd    0    ; Total receive errors
  588. pkts_lost    dd    0    ; Packets dropped - no buffer, out of resc
  589. pd_statistics ends
  590.  
  591. pd_stat        pd_statistics <>    ; An instance of the above
  592.     
  593. PUBLIC    driver_info, access_type, release_type, send_pkt, terminate
  594. PUBLIC    get_address, reset_interface, get_parameters, set_rcv_mode
  595. PUBLIC    get_rcv_mode, get_statistics, set_address
  596.  
  597. ; Normal (basic Packet Driver functions) Jump Table
  598.  
  599. pd_table DW    pd_none        ; No handler
  600.     DW    driver_info    ; 1
  601.     DW    access_type    ; 2
  602.     DW    release_type    ; 3
  603.     DW    send_pkt    ; 4
  604.     DW    terminate    ; 5
  605.     DW    get_address    ; 6
  606.     DW    reset_interface    ; 7
  607. pd_table_size    EQU    ($-pd_table)/2
  608.  
  609. ; High Performance functions Jump Table
  610.  
  611. hp_table DW    get_parameters    ; 10
  612.     DW    pd_none        ; 11 (as_send_pkt not implemented)
  613. hp_table_size    EQU    ($-hp_table)/2
  614.  
  615. ; Extended functions Jump Table
  616.  
  617. ext_table DW    set_rcv_mode    ; 20
  618.     DW    get_rcv_mode    ; 21
  619.     DW    pd_none        ; 22 (set_multicast_list not implemented)
  620.     DW    pd_none        ; 23 (get_multicast_list not implemented)
  621.     DW    get_statistics    ; 24
  622.     DW    set_address    ; 25
  623. ext_table_size    EQU    ($-ext_table)/2
  624.  
  625. ;
  626. ; rcv_lah is the proc that handles ReceiveLookAhead upcalls from the MAC
  627. ;
  628. ; First, it determines if the packet is one that is wanted. If so, it asks
  629. ; the appropriate application for a buffer.  If it gets one, it copies the
  630. ; data and makes the 2nd call to the application to post it complete.  If
  631. ; not, it returns SUCCESS to the DIS driver anyway. It returns SUCCESS if
  632. ; if the packet was copied or FRAME_NOT_RECOGNIZED if it is not in the list
  633. ; of desired types.
  634. ;
  635. ;The stack coming into this call is:
  636. ;    dw    bp[20]        MACID
  637. ;    dw    bp[18]        framesize
  638. ;    dw    bp[16]        bytes available in buffer
  639. ;    dw    bp[14]        lookahead data address seg
  640. ;    dw    bp[12]        lookahead data address off
  641. ;    dd    bp[10]        indicate flag
  642. ;    dw    bp[6]        ds of called protocol mode (ME)
  643. ;
  644.  
  645. rcv_lah    PROC    FAR
  646.     push    bp
  647.     mov    bp,sp
  648.     push    bx            ; -2[bp]    ; save things
  649.     push    cx            ; -4[bp]
  650.     push    dx            ; -6[bp]
  651.     push    di            ; -8[bp]
  652.     push    ds            ; -10[bp]
  653.     push    es            ; -12[bp]
  654.     sub    sp,6            ; -14[bp]  handle
  655.                     ; -16[bp]  seg of PD buffer
  656.                     ; -18[bp]  offset of PD buffer
  657.     push    si
  658.     mov    ax,cs            ; setup data segment
  659.     mov    ds,ax
  660.  
  661.     mov    ax,14[bp]        ; segment of lookahead buffer
  662.     mov    es,ax
  663.     mov    di,12[bp]        ;  and its offset
  664.     call    pktfilter        ; apply packet filter
  665.     jnc    lah_get_buf        ; nc = we want this packet
  666.     mov    ax,FRAME_NOT_RECOGNIZED ; packet not accepted
  667.     jmp    lah_don
  668.  
  669. lah_get_buf:    ; Call Packet Driver receive routine to get its buffer address
  670.     mov    cx,18[bp]        ; CX = packet length
  671.     xor    ax,ax            ; AX = 0, 1st call to receiver
  672.     mov    -14[bp],bx        ; BX = handle, for next call
  673.     push    bp            ; we depend on BP
  674.     call    dword ptr cs:[bx].pd_conn_rcvr    ; Call the receive routine
  675.     pop    bp            ; Get BP back
  676.     mov    ax,es            ; Buffer address is in ES:DI
  677.     or    ax,ax            ; Check for segment of buffer,
  678.     jnz    rcvlha4            ; nz = ok
  679.     or    di,di            ; Check for offset of buffer,
  680.     jnz    rcvlha4            ; nz = ok
  681.     mov    ax,SUCCESS        ; No copy, accept pkt anyway
  682.     jmp    lah_don
  683.  
  684. rcvlha4:                ; Get data into buffer
  685.     mov    -16[bp],es
  686.     mov    -18[bp],di        ; save PD buffer pointer
  687.     mov    ax,offset bytcnt    ; Create far pointer to Addr
  688.     push    ds            ;  to put bytes copied into
  689.     push    ax            ;  and push it 
  690.     xor    ax,ax            ; Starting offset in frame
  691.     push    ax            ;  is always zero
  692. ;
  693. ; Set up recv table description
  694. ;
  695.     mov    ax,18[bp]        ; Len of recv data
  696.     mov    drv_rcv.rcv_len,ax    ;  goes in argument descriptor
  697.     mov    drv_rcv.rcv_seg,es    ;  as does far address of
  698.     mov    drv_rcv.rcv_off,di    ;  receive buffer
  699.     push    ds            ; Push far pointer to
  700.     mov    ax,offset drv_rcv    ;  descriptor
  701.     push    ax
  702.     mov    ax,mac_ds        ; Push MAC's DS value
  703.     push    ax
  704.     call    dword ptr cs:TransferData ; Copy pkt to buf (pops args)
  705. ;
  706. ; Call Packet Driver receive routine again (AX = 1) to finish up
  707. ;
  708.     mov    ax,-16[bp]        ; recover PD buffer pointer
  709.     mov    ds,ax
  710.     mov    si,-18[bp]        ; to DS:SI for second PD call
  711.     mov    cx,18[bp]        ; CX = packet length
  712.     mov    bx,-14[bp]        ; BX = handle
  713.     mov    ax,1            ; AX = 1 (second call)
  714.     call    dword ptr cs:[bx].pd_conn_rcvr    ; Call receive routine again
  715.     mov    ax,SUCCESS        ; we accepted the packet
  716. lah_don:pop    si
  717.     add    sp,6            ; local material
  718.     pop    es
  719.     pop    ds
  720.     pop    di
  721.     pop    dx
  722.     pop    cx
  723.     pop    bx
  724.     pop    bp
  725.     ret    16            ; Pop MAC's params off stack
  726. rcv_lah    ENDP
  727.  
  728. ;
  729. ; rcv_chn is the proc that handles ReceiveChain upcalls from the MAC
  730. ;
  731. ; First, it determines if the packet is one that is wanted. Then it tranfers
  732. ; the data into an internal buffer. it blocks any new indications until the 
  733. ; indicate complete upcall allows it the time to do a packet driver upcall.
  734. ; It returns success if the packet is ok or FRAME_NOT_RECOGNIZED if it is not 
  735. ; in the list of currently open types.
  736. ;
  737. ; The stack coming into this call is:
  738. ;    dw    bp[20]        MACID
  739. ;    dw    bp[18]        framesize
  740. ;    dw    bp[16]        request handle
  741. ;    dw    bp[14]        receive-chain buf descriptor address seg
  742. ;    dw    bp[12]        receive-chain buf descriptor address off
  743. ;    dd    bp[8]        indicate flag addr
  744. ;    dw    bp[6]        DS of called protocol mode (ME)
  745. ;
  746. ; where receive-chain buffer descriptor format is
  747. ;    dw    rxdatacount    count of received data blocks, max of 8
  748. ;    dw    rxdatalen    length of a data block
  749. ;    dd    rxdataptr    seg:offset of a data block
  750.  
  751. rcv_chn    PROC    FAR
  752.     push    bp
  753.     mov    bp,sp
  754.  
  755.     push    bx            ; -2[bp]    ; save things
  756.     push    cx            ; -4[bp]
  757.     push    dx            ; -6[bp]
  758.     push    di            ; -8[bp]
  759.     push    ds            ; -10[bp]
  760.     push    es            ; -12[bp]
  761.     sub    sp,2            ; -14[bp]  handle
  762.     push    si
  763.     mov    ax,cs            ; setup data segment (== CS)
  764.     mov    ds,ax
  765.     mov    ax,14[bp]        ; seg of rcv-chain buffer descriptor
  766.     mov    es,ax
  767.     mov    di,12[bp]        ;  and its offset
  768.     les    di,es:[di+4]        ; es:di is now the buffer pointer
  769.     call    pktfilter        ; apply packet filter, return handle
  770.     jnc    chn_get_buf        ; nc = we want this packet
  771.     mov    ax,FRAME_NOT_RECOGNIZED    ; packet not accepted
  772.     jmp    chn_don
  773.  
  774.     ;; Call the Packet Driver receive routine to get its buffer address
  775. chn_get_buf:
  776.     mov    cx,18[bp]        ; CX = packet length
  777.     xor    ax,ax            ; AX = 1st call to receiver
  778.          mov    -14[bp],bx        ; remember handle for next call
  779.     push    bp            ; We depend on BP
  780.     call    dword ptr cs:[bx].pd_conn_rcvr     ; Call the receive routine
  781.     pop    bp            ; Restore BP
  782.  
  783.     ; Now protocol stack's buffer address is in ES:DI
  784.     mov    ax,es
  785.     or    ax,ax            ; Check for non-zero segment
  786.     jne    rcvchn4            ; ne = ok
  787.     or    di,di            ; Check for non-zero offset
  788.     jne    rcvchn4            ; ne = ok
  789.     mov    ax,SUCCESS        ; No copy, accept pkt anyway
  790.     jmp    chn_don
  791.  
  792. rcvchn4:    ;; Get data from NDIS buffer(s) into protocol stack's buffer
  793.     push    ds            ; Save to restore after call 
  794.     push    es            ; Save ES:DI (pointer) to pass
  795.     push    di            ;  back to receiver later
  796.     lds    si,12[bp]        ; Addr of rcv descriptor
  797.     mov    cx,[si]            ; Get number of data blocks
  798.     add    si,2            ;  & move to top of list
  799.  
  800. chn_dat:        ; Move data from next block into stack's buffer
  801.     push    cx
  802.     push    ds
  803.     push    si
  804.     mov    cx,[si]            ; Get byte count of block
  805.     add    si,2
  806.     lds    si,[si]            ; Get far pointer to data
  807.     cld
  808.     shr    cx, 1
  809.     jnc    rcvchn5            ; nc = even already
  810.     movsb                ; Move 1 byte if count is odd
  811. rcvchn5:rep    movsw            ; Use word mov for efficiency
  812.     pop    si            ; Go through rest of chain
  813.     add    si,6
  814.     pop    ds
  815.     pop    cx
  816.     loop    chn_dat            ; For all blocks
  817. ;
  818. ; Call Packet Driver receive routine again to finish up
  819. ;
  820.     pop    si            ; DS:SI = buffer pointer
  821.     pop    ds            ;  that we're completing
  822.     mov    cx,18[bp]        ; CX = packet length
  823.     mov    bx,-14[bp]        ; BX = handle
  824.     mov    ax,1            ; Indicate 2nd (AX == 1) call
  825.     call    dword ptr cs:[bx].pd_conn_rcvr     ; Call receive routine again
  826.     mov    ax,SUCCESS        ; We accepted the packet
  827.     pop    ds            ; Now we're done with DS
  828.  
  829. chn_don:pop    si
  830.     add    sp,2
  831.     pop    es
  832.     pop    ds
  833.     pop    di
  834.     pop    dx
  835.     pop    cx
  836.     pop    bx
  837.     pop    bp
  838.     ret    16            ; pop params off stack
  839. rcv_chn    ENDP
  840.  
  841. ; Worker for lookahead and receive_chain procedures above. Checks PD handles
  842. ; for wanting this kind of packet. Returns carry clear and BX = handle
  843. ; if packet is wanted, else carry set to reject the packet. Expects MAC layer
  844. ; to provide at least our needed number of bytes (14+).
  845. ; Destroys AX, CX, DX, SI, preserves DI, ES, sets BX. Expects DS = CS.
  846. pktfilter proc    near
  847.     cmp    conn_in_use,0        ; any requests active?
  848.     jnz    pktfil1            ; e = no, exit no-match
  849.     jmp    pktfil11
  850. pktfil1:mov    dx,di            ; es:di is data pointer, save here
  851.     mov    bx,offset handles    ; BX = offset of handle table
  852.     mov    cx,PD_MAX_CONNS        ; CX = entries in table
  853. pktfil2:push    cx            ; save loop counter
  854.     cmp    [bx].pd_conn_used,0    ; is handle in use?
  855.     jne    pktfil4
  856.     jmp    pktfil9            ; e = no, do next handle
  857. pktfil4:lea    si,[bx].pd_conn_type    ; TYPE wanted by this handle
  858.     mov    cx,[bx].pd_conn_type_len; number of bytes to match
  859.     or    cx,cx
  860.     jnz    pktfil6            ; nz = do not match all packets
  861. pktfil5:jmp    pktfil12        ; match all packets
  862. pktfil6:mov    ax,[bx].pd_conn_rmode    ; receive mode
  863.     cmp    ax,6            ; Promiscuous?
  864.     je    pktfil5            ; e = yes, accept packet
  865.     mov    di,dx            ; es:di is lookahead data ptr
  866.     cmp    if_class,3        ; Token Ring 802.5 Class 3 interface?
  867.     jne    pktfil7            ; ne = no
  868.     test    byte ptr es:8[di],80h    ; routing info present? 
  869.     jz    pktfil7            ; z = no
  870.     push    cx
  871.     mov     cl,es:14[di]        ; get length of routing info
  872.     and    cx,1fh            ; just 5 bits worth
  873.     add    di,cx            ; skip over routing info
  874.     pop    cx
  875. pktfil7:add    di,off            ; skip to TYPE field et seq
  876.                     ; do old Novell 802.3 to Type 8137
  877.     cmp    if_class,1        ; regular Ethernet?
  878.     jne    pktfil8            ; ne = no
  879.     cmp    novell,0        ; doing old Novell conversion?
  880.     je    pktfil8            ; e = no
  881.     cmp    word ptr es:[di+2],0ffffh ; have the bad DSAP/SSAP signature?
  882.     jne    pktfil8            ; ne = no
  883.     mov    ax,es:[di]        ; get length/Type field value
  884.     xchg    ah,al            ; low endian form
  885.     cmp    ax,1500            ; size is larger than length?
  886.     jae    pktfil8            ; ae = yes, a protocol type
  887.     mov    word ptr es:[di],3781h    ; force in Novell Type 8137
  888.                     ; end of Novell section
  889. pktfil8:cld
  890.     repe    cmpsb            ; check for matching TYPE
  891.     je    pktfil12            ; e = match
  892.                     ; If Promiscuous mode do manual filter
  893.     cmp    pd_recvall,0        ; doing Promiscuous mode?
  894.     je    pktfil9            ; e = no, next handle
  895.     mov    si,offset address    ; our board's Ethernet addr
  896.     mov    cx,ETHERADDR_LEN    ; length of an Ethernet address
  897.     mov    di,dx            ; lookahead buffer
  898.     add    di,aoff
  899.     cld                ; look at destination address
  900.     repe    cmpsb            ; look for our Ethernet address
  901.     je    pktfil12            ; e = matched, accept lookahead
  902.     cmp    ax,2            ; ignore multicast and broadcast?
  903.     jbe    pktfil9            ; be = yes
  904.     mov    di,dx            ; recover offset of start of buffer
  905.     add    di,aoff
  906.     test    byte ptr es:[di],80h    ; multicast bit set?
  907.     jnz    pktfil12            ; nz = yes, accept lookahead
  908.     cmp    ax,3            ; accepting broadcasts?
  909.     jb    pktfil9            ; b = no
  910.     mov    al,0ffh            ; look for broadcast
  911.     mov    cx,ETHERADDR_LEN
  912.     repe    scasb            ; scan for all 0xFF's
  913.     je    pktfil12            ; e = matched, a broadcast
  914. pktfil9:add    bx,size per_handle    ; next entry
  915.     pop    cx            ; recover loop counter
  916.     dec    cx            ; mechanical loop
  917.     or    cx,cx            ; end of loop?
  918.     jz    pktfil10        ; z = yes
  919.     jmp    pktfil2            ; try next one
  920. pktfil10:mov    di,dx            ; restore di
  921. pktfil11:stc                ; carry set = no match found
  922.     ret
  923.  
  924. pktfil12:pop    cx            ; clean loop counter from stack
  925.     mov    di,dx            ; restore di
  926.     clc                ; carry clear = have match
  927.     ret
  928. pktfilter endp
  929.  
  930. ;
  931. ; Services indication complete upcall
  932. ;
  933. ; Executes interrupt (returned by get_parameters()) to pass control to
  934. ; an application which wants to run after the EOI.
  935. ;
  936. ; NOTE: Interrupt number at label ind_int is over-written if a different
  937. ;    interrupt is configured in protocols.ini.
  938. ;
  939. ind_com    PROC    FAR            ; Indication_complete upcall
  940.     push    es
  941.     push    bx
  942.         xor    ax,ax
  943.     mov    es,ax            ; Point ES at interrupt segment
  944.     mov    bx,cs:param_int        ; Get offset of vector
  945.     or    bx,bx            ; Is there one?
  946.     jz    ind_no_int        ; z = no, don't do the interrupt
  947.     shl    bx,1            ; Multiply by 4 for memory offset
  948.     shl    bx,1
  949.     cmp    word ptr es:[bx]+2,0    ; Is there a segment there?
  950.     jne    ind_int            ; ne = yes
  951.     cmp    word ptr es:[bx],0    ; Is there an offset there?
  952.     je    ind_no_int        ; no, no interrupt
  953. ind_int:                ; INT 65 overwritten if selected
  954.     INT    65h            ; Pass control to the application
  955.  
  956. ind_no_int:
  957.     pop    bx            ; Restore registers
  958.     pop    es
  959.     mov    ax,SUCCESS
  960.     ret    4
  961. ind_com    ENDP
  962.  
  963. ;;;;;;;;;;;;;;;;;;;;;;;;; Packet Driver section 
  964. regs    struc                ; stack offsets of incoming regs
  965.     _ES    dw    ?
  966.     _DS    dw    ?
  967.     _BP    dw    ?
  968.     _DI    dw    ?
  969.     _SI    dw    ?
  970.     _DX    dw    ?
  971.     _CX    dw    ?
  972.     _BX    dw    ?
  973.     _AX    dw    ?
  974.     _IP    dw    ?
  975.     _CS    dw    ?
  976.     _F    dw    ?        ; flags, Carry flag is bit 0
  977. regs    ends
  978. bytes    struc                ; stack offsets of incoming regs
  979.         dw    ?        ; es, ds, bp, di, si are 16 bits
  980.         dw    ?
  981.         dw    ?
  982.         dw    ?
  983.         dw    ?
  984.     _DL    db    ?
  985.     _DH    db    ?
  986.     _CL    db    ?
  987.     _CH    db    ?
  988.     _BL    db    ?
  989.     _BH    db    ?
  990.     _AL    db    ?
  991.     _AH    db    ?
  992. bytes    ends
  993.  
  994. CY    equ    0001h            ; to set caller's carry bit
  995.  
  996. ;
  997. ; Interrupt handler for the Packet Driver interface (protocol stack downcalls)
  998. ;
  999. ; NOTE: Leaves interrupts disabled on entry - code in access_type and
  1000. ;    release_type depends on this.  send_pkt enables interrupts for MAC.
  1001. ;
  1002.     PUBLIC    pd_isr
  1003. pd_isr    PROC    FAR
  1004.     jmp    short over    ; skip the string (this MUST be a 3 byte jmp)
  1005.     nop            ; make three bytes
  1006.           DB    "PKT DRVR",0    ; string to identify a packet driver
  1007. over:
  1008.     push    ax
  1009.     push    bx
  1010.     push    cx
  1011.     push    dx
  1012.     push    si
  1013.     push    di
  1014.     push    bp
  1015.     push    ds
  1016.     push    es
  1017.     cld
  1018.     push    cs            ;set up ds to this code segment
  1019.     pop    ds
  1020.  
  1021.     mov    bp,sp            ;we use bp to access the original regs
  1022.     and    _F[bp],not CY        ;start by clearing the carry flag
  1023.     mov    _DH[bp],0        ; put no-error code in caller's DH
  1024.  
  1025.     cmp    ah,pd_table_size    ; AH too large?
  1026.     jae    highperf_table        ; ae = yes, try next set
  1027.                     ; Dispatch on AH using normal table
  1028.     mov    bl,ah            ; Get function code
  1029.     xor    bh,bh            ;  into a word register
  1030.     shl    bx,1            ; index by words
  1031.     jmp    pd_table[bx]        ; and go
  1032.  
  1033. highperf_table:
  1034.     sub    ah, 10        ; Offset of 1st high-performance function
  1035.     jl    pd_none            ; l = ah is out of range
  1036.     cmp    ah,hp_table_size    ; is AH still in range?
  1037.     jae    xtend_table        ; ae = no, try next set
  1038.                 ; Dispatch on AH using high-performance table
  1039.     mov    bl,ah            ; Get function code
  1040.     xor    bh,bh            ;  into a word register
  1041.     shl    bx,1            ; index by words
  1042.     jmp    hp_table[bx]        ; and go
  1043.  
  1044. xtend_table:
  1045.     sub    ah,10            ; Offset of 1st extended function
  1046.     jl    pd_none            ; l = AH is not in range
  1047.     cmp    ah,ext_table_size     ; still in range?
  1048.     jae    pd_none            ; ae = no
  1049.                     ; Dispatch on AH using extended table
  1050.     mov    bl,ah            ; Get function code
  1051.     xor    bh,bh            ;  into a word register
  1052.     shl    bx,1            ; index by words
  1053.     jmp    ext_table[bx]        ; and go
  1054.  
  1055. pd_none:
  1056.     mov    dh,BAD_COMMAND        ; set error code
  1057. err_ret:
  1058.     mov    _DH[bp],dh        ; put error code in caller's DH
  1059.     or    _F[bp],CY        ; set caller's carry flag
  1060. good_ret:                ; good return (carry clear)
  1061.     pop    es
  1062.     pop    ds
  1063.     pop    bp
  1064.     pop    di
  1065.     pop    si
  1066.     pop    dx
  1067.     pop    cx
  1068.     pop    bx
  1069.     pop    ax
  1070.     iret
  1071.  
  1072. ;
  1073. ; Checks the handle in BX.  If out of range or not valid cleans up the
  1074. ; stack and jumps directly to err_ret with a BAD_HANDLE error.  Assumes
  1075. ; called with DS pushed and a near call.  If handle is good, just returns.
  1076. ; BX is shifted one bit to the left.
  1077. ;
  1078.  
  1079. ; Bounds check on handle
  1080. chk_hdl    PROC     NEAR
  1081.     mov    bx,_BX[BP]        ; Handle
  1082.     cmp    bx,offset handles    ; start of handles area
  1083.     jb    chkhdl1            ; b = out of range
  1084.     cmp    bx,offset end_handles    ; end of handles area
  1085.     jae    chkhdl1            ; ae = above max table size
  1086.     cmp    [bx].pd_conn_used,0    ; is handle used?
  1087.     je    chkhdl1            ; e = no, go bomb out
  1088.     ret                ; return BX as handle
  1089. chkhdl1:
  1090.     pop    ds            ;clear stack (was the return address)
  1091.     mov    dh,BAD_HANDLE        ;return BAD_HANDLE error
  1092.     jmp    err_ret
  1093. chk_hdl    ENDP
  1094.  
  1095. ; The following implement the individual Packet Driver commands, basic
  1096. ; functions first.
  1097. ;
  1098. ; Send a packet.
  1099. ;
  1100. send_pkt:
  1101.     mov    xmt_cmp,REQUEST_QUEUED    ; set up for queued data
  1102.     mov    bx,_BX[bp]        ; handle
  1103.     mov    dx,_DS[bp]        ; get ds of data block to dx
  1104.     mov    cx,_CX[bp]
  1105.     mov    si,_SI[bp]
  1106.     mov    ax,drv_cct.mod_id    ; put our module id
  1107.     push    ax
  1108.     push    ds            ; request handle - good as any
  1109.             ; do conversion of Type 8137 to old Novell 802.3
  1110.     cmp    if_class,1        ; regular Ethernet?
  1111.     jne    send_pkt3        ; ne = no, no conversion
  1112.     cmp    novell,0        ; doing Novell packet conversion?
  1113.     je    send_pkt3        ; e = no
  1114.     push    es
  1115.     mov    es,dx            ; segment of packet
  1116.     cmp    word ptr es:[si+12],3781h ; outgoing Novell Type 8137?
  1117.     jne    send_pkt2        ; ne = no
  1118.     mov    ax,es:[si+12+4]        ; get internal length indicator
  1119.     xchg    ah,al
  1120.     inc    ax            ; round up to an even length
  1121.     and    al,not 1
  1122.     xchg    ah,al
  1123.     mov    es:[si+12],ax        ; change packet Type field to length
  1124. send_pkt2:pop    es            ; end of Novell conversion
  1125.  
  1126. send_pkt3:
  1127.     mov    drv_snd.snd_len,cx    ; save byte count in descriptor
  1128.     mov    drv_snd.snd_off,si    ; store offset of pkt buffer
  1129.     mov    drv_snd.snd_seg,dx    ; store segment of pkt buffer
  1130.     mov    bx,offset drv_snd    ; get addr of xmit buff desc
  1131.     push    ds            ; store on stack
  1132.     push    bx
  1133.     mov    ax,mac_ds        ; MACID
  1134.     push    ax
  1135.     sti                ; enable ints just to be sure
  1136.     call    TransmitChain        ; do downcall to NDIS
  1137.     xor    dx,dx            ; clear return code
  1138.     cmp    ax,SUCCESS        ; done?
  1139.     je    send_pkt4        ; e = yes, success
  1140.     cmp    ax,REQUEST_QUEUED    ; queued?
  1141.     jne    send_pkt5        ; ne = no
  1142. send_pkt4:jmp    good_ret        ; queued is ok
  1143.  
  1144. send_pkt5:
  1145.     mov    dh,CANT_SEND        ; trouble, fail
  1146.     jmp    err_ret
  1147.  
  1148.  
  1149. ;
  1150. ; Handle driver_info() downcall - return driver information.
  1151. ;
  1152. driver_info:
  1153.     mov    bx,pd_version        ; BX is version
  1154.     mov    ch,if_class        ; CH is class
  1155.     mov    dx,if_type        ; DX is type
  1156.     xor    cl,cl            ; CL is interface number (always 0)
  1157.     mov    _BX[bp],bx
  1158.     mov    _CX[bp],cx
  1159.     mov    _DX[bp],dx
  1160.     mov    _SI[bp],offset pd_name    ; ds:si is ptr to name
  1161.     mov    ax,ds
  1162.     mov    _DS[bp],ax
  1163.     mov    al,PD_LEVEL        ; Level of implementation
  1164.     xor    ah,ah
  1165.     mov    _AX[bp],ax
  1166.     jmp    good_ret
  1167.  
  1168. ;
  1169. ; Handle access_type() - sets up to handle an Ethernet packet type.
  1170. ;
  1171. ; NOTE:    Depends on entry with interrupts disabled for shared data locking.
  1172. ;
  1173. access_type_class:
  1174.     mov    dh,NO_CLASS
  1175.     jmp    err_ret
  1176.  
  1177. access_type_type:
  1178.     mov    dh,NO_TYPE
  1179.     jmp    err_ret
  1180.  
  1181. access_type_number:
  1182.     mov    dh,NO_NUMBER
  1183.     jmp    err_ret
  1184.  
  1185. access_type_bad:
  1186.     mov    dh,BAD_TYPE
  1187.     jmp    err_ret
  1188.  
  1189. access_type:
  1190.     mov    al,if_class
  1191.     cmp    _AL[bp],al        ; our class?
  1192.     jne    access_type_class    ; ne = no, fail
  1193. access_type_1:
  1194. ;    cmp    _BX[bp],ANY_TYPE    ; generic type?
  1195. ;    je    access_type_2        ; e = yes
  1196. ;    mov    al,driver_type
  1197. ;    cbw
  1198. ;    cmp    _BX[bp],ax        ; our type?
  1199. ;    jne    access_type_type    ; ne = no
  1200. access_type_2:
  1201.     cmp    _DL[bp],0        ; generic number?
  1202.     je    access_type_3        ; e = yes
  1203.     cmp    _DL[bp],1        ; our number?
  1204.     jne    access_type_number    ; ne = no
  1205. access_type_3:
  1206.     cmp    _CX[bp],MAX_P_LEN    ; is the type length too long?
  1207.     ja    access_type_bad        ; a = yes, this can't be ours
  1208.  
  1209. ; now we do two things--look for an open handle, and check the existing
  1210. ; handles to see if they're replicating a packet type.
  1211.  
  1212.     xor    dx,dx            ; remember no free handle yet
  1213.     mov    bx,offset handles    ; first handle
  1214.     cld
  1215. access_type_4:
  1216.     cmp    [bx].pd_conn_used,0    ; is this handle in use?
  1217.     je    access_type_5        ; e = no, do not check the type
  1218.     mov    al,_AL[bp]        ; is this handle the same class as
  1219.     cmp    al,[bx].pd_conn_class    ;  they want?
  1220.     jne    short access_type_6    ; ne = no
  1221.     mov    es,_DS[bp]        ; get a pointer to their type
  1222.     mov    di,_SI[bp]        ;  from their ds:si to our es:di
  1223.     mov    cx,_CX[bp]        ; get the minimum of their length
  1224.                     ;  and our length.  As currently
  1225.                     ;  implemented, only one receiver
  1226.                     ;  gets the packets, so we have to
  1227.                     ;  ensure that the shortest prefix
  1228.                     ;  is unique.
  1229.     mov    si,[bx].pd_conn_type_len ; length of their Type
  1230.     cmp    cx,si            ; are we less specific than they are?
  1231.     jb    access_type_8        ; b = no
  1232.     mov    cx,si            ; yes, use their (shorter) length
  1233. access_type_8:
  1234.     lea    si,[bx].pd_conn_type    ; their desired Type
  1235.     or    cx,cx            ; pass-all TYPE? (zero TYPE length)
  1236.     jnz    access_type_7        ; nz = no
  1237.     mov    bx,offset handles+(PD_MAX_CONNS-1)*(size per_handle)
  1238.  
  1239.     jmp    short access_type_5    ; put pass-all last
  1240. access_type_7:
  1241.     repe    cmpsb            ; same type? (conflict if so)
  1242.     jne    short access_type_6    ; ne = no, go look at the next one
  1243. access_type_inuse:
  1244.     mov    dh,TYPE_INUSE        ; a handle has been assigned for TYPE
  1245.     jmp    err_ret            ; cannot assign a type
  1246.  
  1247. access_type_5:                ; handle is not in use
  1248.     or    dx,dx            ; found a free handle yet?
  1249.     jne    access_type_6        ; ne = yes
  1250.     mov    dx,bx            ; remember first free handle in dx
  1251. access_type_6:
  1252.     add    bx,(size per_handle)    ; go to the next handle
  1253.     cmp    bx,offset end_handles    ; examined all handles?
  1254.     jb    access_type_4        ; b = no, continue
  1255.     mov    bx,dx            ; did we find a free handle?
  1256.     or    bx,bx
  1257.     jz    access_type_space    ; z = no, return error
  1258.  
  1259.     mov    [bx].pd_conn_used,1    ; remember that we're using it
  1260.     mov    ax,_DI[bp]        ; get receiver address from ES:DI
  1261.     mov    word ptr [bx].pd_conn_rcvr,ax    ; offset part
  1262.     mov    ax,_ES[bp]
  1263.     mov    word ptr [bx].pd_conn_rcvr+2,ax    ; segment part
  1264.  
  1265.     push    ds
  1266.     mov    ax,ds
  1267.     mov    es,ax
  1268.     mov    ds,_DS[bp]        ; remember their type
  1269.     mov    si,_SI[bp]
  1270.     mov    cx,_CX[bp]
  1271.     mov    es:[bx].pd_conn_type_len,cx    ; remember the TYPE length
  1272.     lea    di,[bx].pd_conn_type
  1273.     rep    movsb            ; copy TYPE field to match
  1274.     pop    ds
  1275.     inc    conn_in_use        ; count handles in use
  1276.     mov    al,_AL[bp]        ; remember Class
  1277.     mov    [bx].pd_conn_class,al
  1278.     mov    _AX[bp],bx        ; return handle in caller's AX
  1279.     call    chk_rmode        ; update Promiscous mode status
  1280.     jmp    good_ret
  1281.  
  1282. access_type_space:
  1283.     mov    dh,NO_SPACE
  1284.     jmp    err_ret
  1285. ;
  1286. ; Perform release_type() - forget the packet type/upcall/handle
  1287. ;
  1288. ; NOTE:    Depends on entry with interrupts disabled for shared data locking.
  1289. ;
  1290. release_type:
  1291.     call    chk_hdl            ; get handle, return here if ok
  1292.                     ; This is a critical region!!
  1293.     mov    [bx].pd_conn_type,ETHERTYPE_NONE ; Clear connection
  1294.     mov    [bx].pd_conn_used,0    ; free handle-used indicator
  1295.     dec    conn_in_use        ; Count one less handle open
  1296.     call    chk_rmode        ; update Promiscous mode status
  1297.     jmp    good_ret
  1298. ;
  1299. ; Perform terminate() - never actually do it.
  1300. ;
  1301. terminate:
  1302.     call    chk_hdl            ; check handle
  1303.     mov    dh,CANT_TERMINATE    ; Return error
  1304.     jmp    err_ret
  1305.  
  1306. ;
  1307. ; Perform get_address() - get the current Ethernet address of the interface
  1308. ;
  1309. get_address:
  1310.     mov    ax,_AX[bp]
  1311.     mov    bx,_BX[bp]
  1312.     mov    cx,_CX[bp]
  1313.     mov    si,_SI[bp]
  1314.     mov    di,_DI[bp]
  1315.     mov    es,_ES[bp]
  1316.     cld
  1317.     cmp    cx,ETHERADDR_LEN    ; Make sure it's an ethernet address
  1318.     jne    get_address_err        ; ne = bad length, fail
  1319.     call    get_eaddr        ; address to caller's area
  1320.     mov    ax,ds
  1321.     mov    es,ax
  1322.     mov    di,offset address    ; where to store Ethernet address
  1323.     call    get_eaddr        ; get board's Ethernet address
  1324.     jmp    good_ret
  1325.  
  1326. get_address_err:
  1327.     mov    dh,NO_SPACE        ; hmmm, I suppose it's close enough
  1328.     jmp    err_ret
  1329.  
  1330. ; Return board's current Ethernet address in es:di (ETHERADDR_LEN bytes)
  1331. ; via NDIS information.
  1332. get_eaddr proc    near
  1333.     push    ds
  1334.     push    si
  1335.     push    cx
  1336.     push    es            ; preserve destination
  1337.     push    di
  1338.     les    si,mac_cctp        ; get address of mac cct
  1339.     lds    si,es:sscp[si]        ; get address of mac ssc
  1340.     add    si,cur_add        ; mov to offset in structure
  1341.     pop    di
  1342.     pop    es
  1343.     mov    cx,ETHERADDR_LEN    ; get length
  1344.     cld
  1345.     rep     movsb            ; copy address
  1346.     pop    cx
  1347.     pop    si
  1348.     pop    ds
  1349.     ret
  1350. get_eaddr endp
  1351.  
  1352. ;
  1353. ; Perform reset_interface() - this is ignored.
  1354. ;
  1355. reset_interface:
  1356.     call    chk_hdl            ; check handle
  1357.     jmp    good_ret        ; if the handle was good, call is good
  1358.  
  1359. ;
  1360. ; The following implement the High Performance functions
  1361. ;
  1362. ; get_parameters() - Return pointer to parameters structure in ES:DI
  1363. ;
  1364. get_parameters:
  1365.     mov    ax,cs
  1366.     mov    _ES[bp],ax        ; return struct adr in caller's ES:DI
  1367.     mov    _DI[bp],offset pd_param
  1368.     jmp    good_ret        ;  & pass it to caller
  1369.  
  1370. ;
  1371. ; as_send_pkt() - Not implemented.
  1372. ;
  1373. ;as_send_pkt:
  1374. ;    mov    dh,BAD_COMMAND
  1375. ;    jmp    err_ret
  1376.  
  1377. ;
  1378. ; The following implement the Extended functions
  1379. ;
  1380. ; set_rcv_mode translates the PDS mode to an NDIS Packet Filter.
  1381. ;
  1382. set_rcv_mode:
  1383.     call    chk_hdl            ; get handle, return here if ok
  1384.     mov    ax,_AX[bp]
  1385.     mov    cx,_CX[bp]
  1386.     jcxz    set_rcv_mode_err    ; z = illegal receive mode, quit
  1387.     cmp    cx,6            ; is mode legal?
  1388.     ja    set_rcv_mode_err    ; a = no, quit
  1389.     mov    bx,cx            ; Put it in an index register
  1390.     mov    bl,ndis_mode[bx]    ; and translate it for NDIS
  1391.     xor    bh,bh
  1392.     cmp    bl,4            ; NDIS Promiscuous mode?
  1393.     jb    set_rec_mode2        ; b = no
  1394.     push    es
  1395.     push    di
  1396.     les    di,mac_cctp        ; check if Promiscuous mode supported
  1397.     les    di,es:[di].sscp
  1398.     test    es:[di].svc_1,8        ; first 15 service flags, Promis bit
  1399.     jnz    set_rec_mode1        ; nz = mode is supported
  1400.     dec    bl            ; use regular NDIS mode 3 instead
  1401. set_rec_mode1:
  1402.     pop    di
  1403.     pop    es
  1404. set_rec_mode2:
  1405.     call    set_ndis_mode        ; Try to set it
  1406.     cmp    ax,SUCCESS        ; did it succeed?
  1407.     je    set_rcv_mode_ok        ; e = yes, return success
  1408. set_rcv_mode_err:
  1409.     mov    dh,BAD_MODE        ; no, return error
  1410.     jmp    err_ret
  1411.  
  1412. set_rcv_mode_ok:
  1413.     mov    bx,_BX[bp]        ; get handle again
  1414.     mov    cs:[bx].pd_conn_rmode,cx ; set receive mode in handle's struct
  1415.     mov    cs:pd_rcv_mode,cx    ; save the mode we just set
  1416.     call    chk_rmode        ; check on Promiscous mode
  1417.     jmp    good_ret        ;  and return ok
  1418.  
  1419.  
  1420. ; Examine all PD handles and set global variable pd_recvall to 0 if no handle
  1421. ; is doing Promiscuous mode receives, else non-zero.
  1422. chk_rmode proc    near
  1423.     push    bx
  1424.     push    cx
  1425.     push    ds
  1426.     mov    cx,cs
  1427.     mov    ds,cx
  1428.     mov    bx,offset handles    ; BX = offset of handle table
  1429.     mov    cx,PD_MAX_CONNS        ; CX = entries in table
  1430.     mov    pd_recvall,0        ; assume no Promiscous mode active
  1431. chk_rmode1:
  1432.     cmp    [bx].pd_conn_used,0    ; is handle in use?
  1433.     je    chk_rmode2        ; e = no, do next handle
  1434.     cmp    [bx].pd_conn_rmode,6    ; Promiscuous mode active here?
  1435.     jne    chk_rmode2        ; ne = no
  1436.     mov    pd_recvall,1        ; say Promiscous mode is active
  1437.     jmp    short chk_rmode3
  1438. chk_rmode2:
  1439.     loop    chk_rmode1
  1440. chk_rmode3:
  1441.     pop    ds
  1442.     pop    cx
  1443.     pop    bx
  1444.     ret
  1445. chk_rmode endp
  1446.  
  1447. ;
  1448. ; Return the current Packet Driver receive mode.
  1449. ;
  1450. get_rcv_mode:
  1451.     call    chk_hdl            ; get handle, return here if ok
  1452.     mov    ax,[bx].pd_conn_rmode    ; get mode for this handle
  1453.     mov    _AX[bp],ax
  1454.     jmp    good_ret        ; return it
  1455.  
  1456.  
  1457. get_statistics:
  1458.     les    si,mac_cctp        ; ES:SI == address of NDIS cct
  1459.     les    si,es:sssp[si]        ; ES:SI == address of NDIS sss
  1460.     mov    ax,es
  1461.     or    ax,ax            ; Is the segment non-zero?
  1462.     jnz    getsta1            ; nz = yes, accept it
  1463.     or    si,si            ; how about offset?
  1464.     jnz    getsta1            ; nz = ok
  1465.     mov    DH,BAD_COMMAND        ; If they don't implement it,
  1466.     jmp    err_ret            ;  neither do we
  1467.     
  1468. getsta1:mov    ax,cs
  1469.     mov    ds,ax
  1470.     mov    di,offset pd_stat        ; Get start of PD stats table
  1471.     cli                    ; Don't allow updates just now
  1472.     mov    ax,WORD PTR es:r_tot[si]    ; Copy total received frames
  1473.     mov    dx,WORD PTR es:r_tot+2[si]
  1474.     call    valchk
  1475.     mov    ax, WORD PTR es:x_tot[si]    ; Copy total xmitted frames
  1476.     mov    dx, WORD PTR es:x_tot+2[si]
  1477.     call    valchk
  1478.     mov    ax, WORD PTR es:rb_tot[si]    ; Copy total received bytes
  1479.     mov    dx, WORD PTR es:rb_tot+2[si]
  1480.     call    valchk
  1481.     mov    ax, WORD PTR es:xb_tot[si]    ; Copy total transmitted bytes
  1482.     mov    dx, WORD PTR es:xb_tot+2[si]
  1483.     call    valchk
  1484.     mov    ax, WORD PTR es:r_err[si]    ; Copy total receive errors
  1485.     mov    dx, WORD PTR es:r_err+2[si]
  1486.     call    valchk
  1487.     mov    ax, WORD PTR es:x_hwer[si]    ; Copy total transmit errors
  1488.     mov    dx, WORD PTR es:x_hwer+2[si]
  1489.     call    valchk
  1490.     mov    ax, WORD PTR es:r_drop[si]    ; Copy total receives dropped
  1491.     mov    dx, WORD PTR es:r_drop+2[si]
  1492.     call    valchk
  1493.     sti                    ; All done with shared data
  1494.     mov    _SI[bp],OFFSET pd_stat      ; set caller's DS:SI to the
  1495.     mov    ax,cs            ; address of Packet Driver stats
  1496.     mov    _DS[bp],ax
  1497.     jmp    good_ret
  1498.  
  1499. ; Convert double word dx:ax from NDIS unknown value of (long) -1 to (long) 0,
  1500. ; store results in ds:[di, di+2], move di forward two words.
  1501. valchk    proc    near
  1502.     cmp    ax,-1            ; starting at -1 (NDIS, for unknown)?
  1503.     jne    valchkx            ; ne = no
  1504.     cmp    dx,-1            ; this part too
  1505.     jne    valchkx            ; ne = no
  1506.     xor    ax,ax            ; zero counters for zero based counts
  1507.     xor    dx,dx
  1508. valchkx:mov    [di],ax            ; store results locally
  1509.     mov    [di+2],dx
  1510.     add    di,4            ; step to next storage double word
  1511.     ret
  1512. valchk    endp
  1513. ;
  1514. ; Perform set_address() - change physical address of the interface.
  1515. ;
  1516. ; The problem with this is that some NDIS drivers may just accept the
  1517. ; SetStationAddress call, but others may require a CloseAdapter/OpenAdapter
  1518. ; to bracket it.  This latter doesn't seem worth the effort at the moment.
  1519. ;
  1520. set_address:
  1521. IFDEF    DO_SET_ADDRESS
  1522.     
  1523.     mov    bx,_BX[bp]        ; Get handle (not checked)
  1524.     mov    cx,_CX[bp]
  1525.     cmp    cx,ETHERADDR_LEN    ; Make sure it's an ethernet address
  1526.     jne    set_address_err        ; Jump if bad length
  1527.  
  1528.     cmp    conn_in_use,1        ; How many handles are open?
  1529.     jbe    set_allowed        ; be = 1 or none, ok
  1530. set_err:
  1531.     mov    dh,CANT_SET        ; Too many - don't allow it
  1532.     jmp    err_ret
  1533.  
  1534. set_allowed:
  1535.     mov    ax, cs:drv_cct.mod_id    ; Make set station address call
  1536.     push    ax            ; Module ID of protocol
  1537.     inc    ax
  1538.     push    ax            ; Push request ID (0 to not conf)
  1539.     xor    bx,bx
  1540.     push    bx            ; Must be 0
  1541.     push    es            ; Push pointer to address to set
  1542.     push    di
  1543.     push    SET_STA_ADDR        ; SetStationAddress function code
  1544.     les    bx,mac_cctp
  1545.     mov    ax,es:[bx].mod_ds
  1546.     push    ax
  1547.     mov    cs:req_con_flg,REQUEST_QUEUED
  1548.     call    cs:Request        ; Make call to NDIS
  1549.     mov    cs:req_con_flg,ax
  1550.     sti                ; Wait for request to complete
  1551. setall1:
  1552.     cmp    ax,SUCCESS        ; success?
  1553.     je    setall2            ; e = yes
  1554.     cmp    ax,REQUEST_QUEUED    ; Is it queued?
  1555.     jne    set_err            ; ne = no, quit with CANT_SET
  1556.     mov    ax,cs:req_con_flg    ; get current status
  1557.     jmp    short setall1        ; keep polling
  1558. setall2:jmp    good_ret
  1559.  
  1560. set_address_err:
  1561.     mov    dh, BAD_ADDRESS        ; We didn't like the address
  1562.     jmp    err_ret
  1563. ELSE
  1564.     mov    dh, CANT_SET        ; Built this way, we can't set address
  1565.     jmp    err_ret
  1566. ENDIF
  1567.  
  1568. pd_isr    ENDP
  1569. ;;;;;; end of Packet Driver direct support procedures
  1570.  
  1571. ;
  1572. ; The following are upcalls from DIS:
  1573.  
  1574. ; RequestConfirm enters with stack of (after our push bp)
  1575. ;    dw    [BP+16]        ProtID
  1576. ;    dw    [BP+14]        MACID
  1577. ;    dw    [BP+12]        ReqHandle
  1578. ;    dw    [BP+10]        Status
  1579. ;    dw    [BP+8]        Request
  1580. ;    dw    [BP+6]        ProtDS (our DS)
  1581.  
  1582. req_con    PROC    FAR            ; Request Confirm 
  1583.     push    bp
  1584.     mov    bp,sp
  1585.     mov    ax,[bp+10]        ; get NDIS status response
  1586.     mov    cs:req_con_flg,ax    ; store in local area
  1587.     mov    ax,SUCCESS        ; return our feelings on the matter
  1588.     pop    bp
  1589.     ret    12
  1590. req_con    ENDP
  1591.  
  1592.  
  1593. ; TransmitConfirm enters with stack of (after our push bp)
  1594. ;    dw    [BP+14]        ProtID        
  1595. ;    dw    [BP+12]        MACID        
  1596. ;    dw    [BP+10]        ReqHandle
  1597. ;    dw    [BP+8]        Status        
  1598. ;    dw    [BP+6]        ProtDS (our DS)
  1599.         
  1600. xmt_con    PROC    FAR            ; Transmit Confirm
  1601.     push    bp
  1602.     mov    bp,sp
  1603.     mov    ax,8[bp]
  1604.     mov    cs:xmt_cmp,ax        ; moves the return code into static
  1605.     mov    ax,SUCCESS
  1606.     pop    bp
  1607.     ret    10
  1608. xmt_con    ENDP
  1609.  
  1610.  
  1611. sta_ind    PROC    FAR            ; Status handled, not used
  1612.     mov    ax,SUCCESS
  1613.     ret    12
  1614. sta_ind    ENDP
  1615.  
  1616.  
  1617. dis_pat    PROC    FAR            ; System entry point for pkt driver
  1618.     push    bp            ; Used only by initiate bind request
  1619.     mov    bp,sp
  1620.     mov    ax,8[bp]        ; Check opcode
  1621.     cmp    ax,1            ; Is it initiate_bind?
  1622.     je    dispat1            ; e = yes            
  1623.     mov    ax,GENERAL_FAILURE    ; NO: fail
  1624.     pop    bp
  1625.     ret    14
  1626.  
  1627. dispat1:push    ds            ; save stuff
  1628.     push    es
  1629.     push    bx
  1630.     push    cx
  1631.     push    si
  1632.     push    di
  1633.  
  1634.     mov    ax,cs            ; set up DS == CS
  1635.     mov    ds,ax            
  1636.     mov    bx,offset mac_cctp    ; Save addr of MAC's cct
  1637.     mov    ax,12[bp]
  1638.     mov    [bx],ax
  1639.     mov    ax,14[bp]
  1640.     mov    2[bx], ax
  1641.  
  1642.     mov    ax,offset drv_cct    ; push pkt drv cct (our cct)
  1643.     push    ds            
  1644.     push    ax
  1645.     mov    ax,offset mac_cctp    ; push addr for MAC's cct
  1646.     push    ds
  1647.     push    ax
  1648.     xor    ax,ax            ; pad parameter
  1649.     push    ax
  1650.     mov    ax,2            ; Load Bind command code
  1651.     push    ax
  1652.     les    bx,mac_cctp        ; load address of MAC's cct
  1653.     mov    ax,es:[bx].mod_ds
  1654.     push    ax            ; push MAC's ds
  1655.     call    dword ptr es:[bx].system ; call MAC's system entry point
  1656.     mov    rtn_cod,ax        ; remember return status
  1657.     or    ax,ax
  1658.     jz    dispat2            ; z = Bind succeeded
  1659.     MSG    bad_bind        ; tell the user the bad news
  1660.     jmp    rtn_dis            ; Bind failed, fatal error
  1661.  
  1662. dispat2:
  1663.     call    sav_mac            ; Save MAC entry point addresses
  1664.     les    bx,mac_cctp        ; Check if OpenAdapter needed
  1665.     les    bx,es:[bx].sscp
  1666.  
  1667.     lea    di,[bx].mtype        ; MAC type, asciiz
  1668.     mov    si,offset t8023        ; try 802.3
  1669.     mov    cx,t8023len
  1670.     cld
  1671.     repe    cmpsb
  1672.     je    is8023            ; e = matched
  1673.     lea    di,[bx].mtype
  1674.     mov    si,offset t8025        ; try 802.5 (Token Ring)
  1675.     mov    cx,t8025len
  1676.     repe    cmpsb
  1677.     je    is8025            ; e = matched
  1678.     jmp    short gottype
  1679. is8023:    mov    if_class,11        ; 802.3 with 802.2 (SNAP) headers
  1680.     mov    off,14            ; 6 MAC + 6 MAC + 2 LEN
  1681.     jmp    short gottype
  1682. is8025:    mov    if_class,3        ; Token Ring 802.5
  1683.     mov    off,14
  1684.     mov    aoff,2
  1685.     mov    ax,es:[bx].maxfram
  1686.     mov    mtu,ax
  1687. ;    jmp    short gottype
  1688.  
  1689. gottype:mov    ax,es:[bx].svc_1
  1690.     test    ax,0800h         ; OpenAdapter supported?
  1691.     jnz    dispat3            ; nz = yes, go do it
  1692.     jmp    open_ok1        ; skip to setting packet filter
  1693.  
  1694. dispat3:                ; Make OpenAdapter call to NDIS
  1695.     mov    ax,cs
  1696.     push    ax            ; module ID of protocol
  1697.     push    ax            ; unique handle (0 to not conf)
  1698. ifdef    ALLFRAMES
  1699.     mov    ax, 6
  1700.     push    ax
  1701. endif
  1702.     xor    ax,ax
  1703. ifndef    ALLFRAMES
  1704.     push    ax            ; dw pad
  1705. endif
  1706.     push    ax            ; dd pad
  1707.     push    ax
  1708.     mov    ax,OPEN_ADAPTER        ; OpenAdapter command code
  1709.     push    ax
  1710.     les    bx,mac_cctp
  1711.     mov    ax,es:[bx].mod_ds
  1712.     push    ax
  1713.     mov    cs:req_con_flg,REQUEST_QUEUED
  1714.     call    cs:Request        ; Make call to NDIS via indirect ptr
  1715.     mov    cs:req_con_flg,ax    ; Save immediate return code
  1716.  
  1717. dispat4:sti                ; Needed because of bugs in some MACs
  1718.     cmp    ax,SUCCESS
  1719.     jz    open_ok1
  1720.     cmp    ax,NOT_SUPPORTED
  1721.     jz    open_ok1
  1722.     cmp    ax,REQUEST_QUEUED    ; Was it queued?
  1723.     jne    dispat5            ; NO: bomb
  1724.     mov    ax,cs:req_con_flg
  1725.     jmp    short dispat4        ; keep polling
  1726.  
  1727. dispat5:MSG    bad_open_adpt        ; Fatal error: open adapter failed
  1728.     jmp    rtn_dis
  1729.  
  1730. open_ok1:
  1731.     mov    ax,cs            ; Temp fix for Apricot (may not
  1732.     mov    ds,ax            ;  be needed anymore)
  1733.     mov    ax,mac_ds
  1734.     push    ax
  1735.     call    IndicationOff
  1736.     mov    ax,mac_ds
  1737.     push    ax
  1738.     call    IndicationOn
  1739.     sti                ; Who disabled?  MAC bug probably
  1740.  
  1741.     mov    bx,3            ; Set default filter: Directed,
  1742.     call    set_ndis_mode        ;  Multicast & Broadcast (3)
  1743.     cmp    ax,SUCCESS        ; Did it work?
  1744.     je    set_vec            ; e = yes, go on to vector
  1745.     MSG    bad_set_pkt        ; show an error and fail
  1746.     jmp    rtn_dis
  1747.  
  1748. ; Give warning if the Packet Driver vector is already in use but use anyway
  1749.  
  1750. set_vec:
  1751.     xor    ax,ax            ; Set ES to 0 to look in int tab
  1752.     mov    es,ax
  1753.     mov    bx,cs:pd_vector        ; Get vector and multiply by 4
  1754.     shl    bx,1
  1755.     shl    bx,1
  1756.     mov    ax,es:[bx]
  1757.     or    ax,ax            ; Is segment zero?
  1758.     jnz    vin_use2        ; nz = yes, print warning
  1759.     mov    ax,es:2[bx]
  1760.     or    ax,ax            ; Is offset zero?
  1761.     jz    dispat6            ; z = no, don't print warning
  1762.  
  1763. vin_use2:
  1764.     MSG    vec_in_use        ; Print a warning
  1765. dispat6:
  1766.     mov    ax,offset pd_isr    ; move packet driver isr addr into
  1767.     mov    es:[bx],ax        ; interrupt vector table
  1768.     mov    ax,cs
  1769.     mov    es:2[bx],ax
  1770.     xor    ax,ax
  1771. rtn_dis:
  1772.     pop    di            ; all done
  1773.     pop    si
  1774.     pop    cx
  1775.     pop    bx
  1776.     pop    es
  1777.     pop    ds
  1778.     pop    bp
  1779.     ret    14
  1780. dis_pat    ENDP
  1781.  
  1782. ; Make the NDIS SetPktFilter call (both at bind and from set_rcv_mode)
  1783. ;
  1784. ; Arguments:
  1785. ;    BX    NDIS Packet filter to set (see DIS p 45 for bits)
  1786. ;         * 0 - directed and multicast
  1787. ;         * 1 - broadcast
  1788. ;           2 - promiscuous
  1789. ;           3 - any source routing packet
  1790. ;
  1791. set_ndis_mode PROC NEAR
  1792.     push    es            ; Save ES & BX registers
  1793.     push    bx
  1794.     mov    ax,cs:drv_cct.mod_id    ; make set packet filter call
  1795.     push    ax            ; module ID of protocol
  1796.     inc    ax
  1797.     push    ax            ; unique handle (0 to not conf)
  1798.     push    bx            ; Push packet filter value
  1799.     xor    ax,ax
  1800.     push    ax            ; dd pad
  1801.     push    ax
  1802.     mov    ax,SET_PKT_FLT        ; SetPacketFilter command
  1803.     push    ax
  1804.     les    bx,mac_cctp
  1805.     mov    ax,es:[bx].mod_ds
  1806.     push    ax
  1807.     mov    cs:req_con_flg,REQUEST_QUEUED
  1808.     call    cs:Request        ; Make call to NDIS
  1809.     mov    cs:open_adap,ax
  1810.     sti                ; Wait for request to complete
  1811. setndmode1:
  1812.     cmp    ax,SUCCESS        ; done?
  1813.     jz    setndmode2        ; z = yes, success
  1814.     cmp    ax,REQUEST_QUEUED    ; Is it queued?
  1815.     jne    setndmode2        ; ne = no, fail
  1816.     mov    ax,cs:req_con_flg    ; get current status
  1817.     jmp    setndmode1        ; keep polling
  1818. setndmode2:
  1819.     pop    bx
  1820.     pop    es
  1821.     ret                ; NDIS return code is in AX
  1822. set_ndis_mode ENDP
  1823.  
  1824. ;
  1825. ; Put MAC entry points into static locations - called at bind time.
  1826. ;
  1827. sav_mac    PROC    NEAR
  1828.     push    ax
  1829.     les    si,mac_cctp
  1830.     mov    ax,es:[si].mod_ds    ; save MAC ds
  1831.     mov    mac_ds, ax
  1832.     les    si,es:[si].udtp
  1833.  
  1834.     mov    bx,offset Request    ; save request entry point
  1835.     mov    ax, es:4[si]
  1836.     mov    [bx],ax
  1837.     mov    ax,es:6[si]
  1838.     mov    2[bx], ax
  1839.  
  1840.     mov    bx,offset TransmitChain    ; save xmt block entry point
  1841.     mov    ax,es:8[si]
  1842.     mov    [bx],ax
  1843.     mov    ax,es:10[si]
  1844.     mov    2[bx],ax
  1845.  
  1846.     mov    bx,offset TransferData    ; save xfer data entry point
  1847.     mov    ax,es:12[si]
  1848.     mov    [bx],ax
  1849.     mov    ax,es:14[si]
  1850.     mov    2[bx],ax
  1851.  
  1852.     mov    bx,offset ReceiveRelease ; save recv rel entry point
  1853.     mov    ax,es:16[si]
  1854.     mov    [bx],ax
  1855.     mov    ax,es:18[si]
  1856.     mov    2[bx],ax
  1857.  
  1858.     mov    bx,offset IndicationOn    ; save ind on entry point
  1859.     mov    ax,es:20[si]
  1860.     mov    [bx],ax
  1861.     mov    ax,es:22[si]
  1862.     mov    2[bx],ax
  1863.  
  1864.     mov    bx,offset IndicationOff    ; save ind off entry point
  1865.     mov    ax,es:24[si]
  1866.     mov    [bx],ax
  1867.     mov    ax,es:26[si]
  1868.     mov    2[bx],ax
  1869.     pop    ax
  1870.     ret
  1871. sav_mac    ENDP
  1872.  
  1873. ; Message strings needed at bind time.
  1874.  
  1875. bad_open_adpt    db    "Adapter did not open", EOL
  1876. bad_set_pkt    db    "Set packet filter failed", EOL
  1877. vec_in_use    db    "Vector already in use", EOL
  1878. bad_bind    db    7,"BIND failed",EOL
  1879. t8023        db    '802.3',0
  1880. t8023len    equ    $-t8023
  1881. t8025        db    '802.5',0
  1882. t8025len    equ    $-t8025
  1883.  
  1884. end_res:    ;;;; Currently not keeping init code in memory
  1885.  
  1886. ;
  1887. ; DOS device driver interrupt entry point.
  1888. ;
  1889. ; This is used to initialize module and read parameters from PROTOCOLS.INI
  1890. ; only, and frees itself after startup.  The NDIS bind takes place later,
  1891. ; via dis_pat and its friends above.
  1892. ;
  1893. intr    PROC    FAR
  1894.     push    es            ; save all registers
  1895.     push    ds
  1896.     push    si
  1897.     push    di
  1898.     push    dx
  1899.     push    cx
  1900.     push    bx
  1901.     push    ax
  1902.  
  1903.     mov    ax,cs            ; check to see if already initialized
  1904.     mov    ds,ax
  1905.     mov    al,init_flg        ; our init flag
  1906.     or    al,al            ; not inited yet (0)?
  1907.     jz    intr1            ; z = yes, init now
  1908.  
  1909.     mov    bx,req_off        ; already initialized - return 
  1910.     mov    ds,req_seg        ;  with error
  1911.     mov    [bx].status, 810Ch
  1912.     jmp    rtn
  1913.  
  1914. intr1:    cli                ; not initialized - switch to new 
  1915.     mov    si,SS            ;  stack and init
  1916.     mov    dx,SP        
  1917.     mov    ax,CS
  1918.     mov    SS,ax        
  1919.     mov    SP,OFFSET new_stk    ; Need a big stack for this call
  1920.     STI                ; Critical region
  1921.     PUSH    SI            ; Save old SS
  1922.     PUSH    DX            ;  and SP
  1923.     MSG    msg_copyright        ; Display copyright notice
  1924.     call    init            ; Init this driver
  1925.  
  1926.     mov    ax,cs            ; Set DS == CS
  1927.     mov    ds,ax
  1928.     mov    bx,req_off        ; Get request header ptr
  1929.     mov    es,req_seg
  1930.     mov    word ptr es:[bx].status,0100h    ; Set return status ok
  1931.     mov    init_flg,1        ; Note that we've initialized
  1932.     mov    ax,offset end_res    ; Set end of resident code
  1933.     mov    word ptr es:[bx].end_off,ax
  1934.     mov    ax,cs
  1935.     mov    es:[bx].end_seg,ax
  1936.  
  1937.     POP    DI            ; Old SP
  1938.     POP    SI            ;  and old SS
  1939.     CLI                ; Critical region
  1940.     mov    SS, SI            ; Change back to old stack
  1941.     mov    SP, DI
  1942.     STI                ; End critical region
  1943. rtn:    pop    ax            ; All done
  1944.     pop    bx
  1945.     pop    cx
  1946.     pop    dx
  1947.     pop    di
  1948.     pop    si
  1949.     pop    ds
  1950.     pop    es
  1951.     ret
  1952. intr    ENDP
  1953.  
  1954.     db    512 dup (0)
  1955. new_stk    label    word        ; A stack for init to use
  1956.     db    4 dup (0)
  1957. fil_han    dw    0        ; File handle for init
  1958.  
  1959. ;
  1960. ; Initialize the converter module - read parameters from PROTOCOLS.INI.
  1961. ;
  1962. init    PROC    NEAR
  1963.     mov    ax,cs            ; open the Protocol Manager driver
  1964.     mov    ds,ax
  1965.     mov    ah,fopen              ; open file
  1966.     mov    al,0C2h          
  1967.     mov    dx,offset pm__nam    ; device name
  1968.     int    dos
  1969.     jnc    init1                  ; nc = success
  1970.     MSG    pro_no_open        ; error
  1971.     jmp    init_err
  1972.  
  1973. init1:    mov    fil_han,ax        ; file handle
  1974.     mov    bx, ax
  1975.     mov    ax, cs
  1976.     mov    ds, ax
  1977.     mov    drv_req.req_opc,1    ; make GetProtocolManagerInfo call
  1978.     mov    drv_req.req_sta,-1    ; zero out return status
  1979.     mov    drv_req.req_of1,-1    ; NULL out pointers
  1980.     mov    drv_req.req_sg1,-1
  1981.     mov    drv_req.req_of2,-1    ; NULL out pointer 2
  1982.     mov    drv_req.req_sg2,-1
  1983.     mov    drv_req.req_prm,-1    ; zero out parameter word
  1984.     
  1985.     mov    ah,ioctl        ; IOCTL req
  1986.     mov    al,02h            ; device input
  1987.     mov    dx,offset drv_req    ; pointer to buffer
  1988.     mov    cx,14            ; size of buffer
  1989.     int    dos            ; call DOS
  1990.     jnc      init2            ; nc = success
  1991.     MSG    pro_bad_gpm        ; Error: print msg & bomb
  1992.     jmp    init_err
  1993.  
  1994. init2:    mov    ax, cs            ; restore ds
  1995.     mov    ds, ax
  1996.  
  1997.     mov    ax,offset pro_nam    ; Get name of module to bind to,
  1998.     push    ax            ;  returned by get_pro in ES:DI
  1999.     mov    ax,pro_nam_len
  2000.     push    ax
  2001.     mov    ax,offset pro_bnd_to
  2002.     push    ax
  2003.     mov    ax,pro_bnd_to_len
  2004.     push    ax
  2005.     xor    ax,ax
  2006.     push    ax
  2007.     call    get_pro            ; Try to find the token we want
  2008.     or    di,di            ; Was it there?
  2009.     jnz    init4            ; nz = yes, parse it
  2010.     mov    drv_bnd.bnd_cnt,0    ; else say nothing bound
  2011.     jmp    short init45
  2012.  
  2013. init4:    push    ds            ; Save name in bindings structure
  2014.     push    ds            ; currently allowed to bind to only
  2015.     push    es            ;  one MAC
  2016.     pop    ds
  2017.     pop    es
  2018.     mov    si,di
  2019.     mov    di,offset drv_bnd.bnd_nam
  2020.     mov    cx,-2[si]
  2021.     cld
  2022.     rep    movsb
  2023.     pop    ds
  2024.  
  2025. init45:    mov    ax,offset pro_nam    ; Get Packet Driver vector to use
  2026.     push    ax
  2027.     mov    ax,pro_nam_len
  2028.     push    ax
  2029.     mov    ax,offset pro_prm_vec    ; "INTVEC" keyword
  2030.     push    ax
  2031.     mov    ax,pro_prm_vec_len
  2032.     push    ax
  2033.     xor    ax,ax
  2034.     push    ax
  2035.     call    get_pro            ; Go look for the token
  2036.     or    di,di            ; Was the token found?
  2037.     jnz    init5            ; nz = yes
  2038.     MSG    vec_not_spc        ; abort if not found
  2039.     jmp    init_err
  2040.  
  2041. init5:    mov    dx,es:[di]        ; check that vector is in range
  2042.     cmp    dx,80h            ; 0x80 is high limit
  2043.     jge    bad_vec2
  2044.     cmp    dx,60h            ; 0x60 is low limit
  2045.     jl    bad_vec2
  2046.     mov    pd_vector,dx        ; Save value for bind time
  2047.     jmp    short init6        ; Go on to EOI interrupt
  2048.  
  2049. bad_vec2:
  2050.     MSG    msg_bad_vec        ; Abort if out of range
  2051.     jmp    init_err
  2052.  
  2053. init6:    mov    ax,offset pro_nam    ; Get EOI interrupt (if any)
  2054.     push    ax 
  2055.     mov    ax,pro_nam_len
  2056.     push    ax
  2057.     mov    ax,offset pro_daisy_vec ; "CHAINVEC" key word
  2058.     push    ax         
  2059.     mov    ax,pro_daisy_len
  2060.     push    ax
  2061.     xor    ax,ax
  2062.     push    ax
  2063.     call    get_pro            ; Try to find the token
  2064.     or    di,di
  2065.     jz    init7            ; z = no interrupt
  2066.  
  2067.     mov    dx,es:[di]        ; Check that interrupt is ok
  2068.     cmp    dx,80h            ; High limit is 0x80
  2069.     jae    bad_vec3        ; ae = above high limit
  2070.     cmp    dx,60h            ; Low limit is 0x60
  2071.     jb    bad_vec3        ; b = below lower limit
  2072.     mov    byte ptr ind_int+1,dl    ; Modify the code
  2073.     mov    param_int, dx        ; Save interrupt number
  2074.     jmp    short init7        ; Go do the RegisterModule
  2075.  
  2076. bad_vec3:
  2077.     MSG    msg_bad_vec
  2078.     jmp    init_err        ; Abort installation
  2079.  
  2080. init7:    mov    ax,offset pro_nam    ; Get old Novell 802.3 keyword
  2081.     push    ax 
  2082.     mov    ax,pro_nam_len
  2083.     push    ax
  2084.     mov    ax,offset pro_novell    ; "NOVELL" key word
  2085.     push    ax         
  2086.     mov    ax,pro_nov_len
  2087.     push    ax
  2088.     xor    ax,ax
  2089.     push    ax
  2090.     mov    novell,0        ; assume no token
  2091.     call    get_pro            ; Try to find the token
  2092.     or    di,di
  2093.     jz    init8            ; z = no token
  2094.     mov    dx,es:[di]        ; get the token's value
  2095.     and    dl,not 20h        ; to upper case
  2096.     cmp    dl,'Y'            ; "yes"?
  2097.     jne    init8            ; ne = no conversion
  2098.     mov    novell,1        ; set flag
  2099.     MSG    novmsg            ; tell the user about conversion
  2100.  
  2101. init8:    call    pkt_ptr            ; Initialize the LDT and CCT pointers
  2102.     mov    ax,cs
  2103.     mov    ds,ax
  2104.     mov    drv_req.req_opc,2    ; RegisterModule call
  2105.     mov    drv_req.req_sta,0    ; zero out return status
  2106.     mov    drv_req.req_of1,offset drv_cct ; cct pointer
  2107.     mov    drv_req.req_sg1,ax
  2108.     mov    drv_req.req_of2,offset drv_bnd
  2109.     mov    drv_req.req_sg2,ax
  2110.     mov    drv_req.req_prm,0    ; zero out parameter word
  2111.     mov    ah,ioctl        ; IOCTL call
  2112.     mov    al,2
  2113.     mov    dx,offset drv_req
  2114.     mov    cx,14
  2115.     mov    bx,fil_han
  2116.     int    dos
  2117.     mov    ax,drv_req.req_sta    ; check return status
  2118.     cmp    ax,SUCCESS
  2119.     je    init9            ; e = success
  2120.     mov    cs:rtn_cod,ax        ; abort if reg mod failed
  2121.     MSG    reg_mod_nok
  2122.     jmp    init_err
  2123.  
  2124. init9:    mov    bx,fil_han        ; Close protman device
  2125.     mov    ah,fclose
  2126.     int    dos
  2127.     jc    init10            ; c = failure
  2128.     xor    ax,ax            ; Indicate success
  2129.     ret                ;  & do normal return
  2130.  
  2131. init10:    MSG    msg_err_clo        ; close failed, quite unlikely
  2132.     jmp    init_err
  2133.  
  2134. init_err:mov    ax,1            ; error return
  2135.     ret
  2136. init    ENDP
  2137.  
  2138. ; get_pro returns a pointer to the keyword entry from GPMI call
  2139. ;    12[bp] is a pointer to module name
  2140. ;    10[bp] is length of module name
  2141. ;    8[bp] is a pointer to keyword name
  2142. ;    6[bp] is length of keyword name
  2143. ;    4[bp] is number of parameter wanted from specified keyword
  2144. ;
  2145. ; returns
  2146. ;    es:bx is pointer to param
  2147. ;    ax zero for ok and !0 for not found
  2148. ;
  2149. get_pro    PROC    NEAR
  2150.     push    bp
  2151.     mov    bp,sp
  2152.     push    ds
  2153.     push    bx
  2154.     push    si
  2155.     lds    bx,dword ptr drv_req.req_of1    ; ConMemIma pointer
  2156.  
  2157.     mov    ax,cs                ; find module name
  2158.     mov    es,ax
  2159. getpro1:mov    ax,ds                ; quit if pointer NULL (eol)
  2160.     or    ax,ax
  2161.     jz    err_get_pro            ; z = error
  2162.     mov    di,12[bp]            ; module name
  2163.     mov    si,bx                ; set up to point name
  2164.     add    si,8
  2165.     mov    cx,10[bp]            ; module name length
  2166.     cld
  2167.     repe    cmpsb                ; right module name?
  2168.     je    pro_fnd                ; e = module name found
  2169.     lds    bx,dword ptr [bx]        ; not found-load next in chain
  2170.     jmp    short getpro1
  2171.  
  2172. pro_fnd:
  2173.     add    bx,24                ; offset of parameter pointers
  2174. getpro2:
  2175.     mov    ax,ds
  2176.     or    ax,ax
  2177.     jz    err_get_pro
  2178.     mov    di,8[bp]            ; parameter name
  2179.     mov    cx,6[bp]            ; parameter name length
  2180.     mov    si,bx
  2181.     add    si,8
  2182.     cld
  2183.     repe    cmpsb
  2184.     je    key_fnd                ; e = parameter found
  2185.     lds    bx,dword ptr [bx]        ; not found-load next in chain
  2186.     jmp    short getpro2
  2187. key_fnd:
  2188.     add    bx,24                ; offset of values
  2189.     mov    cx,4[bp]            ; check if enough values are 
  2190.     cmp    cx,[bx]                ; here
  2191.     jge    err_get_pro
  2192.     add    bx,2                ; position to the value
  2193.     jcxz    prm_fnd                ; may be either char string
  2194. getpro3:                    ;  or number depending on type
  2195.     add    bx,2
  2196.     add    bx,[bx]
  2197.     add    bx,2
  2198.     loop    getpro3
  2199. prm_fnd:
  2200.     mov    si,bx                ; set es:di to point to value
  2201.     add    si,4
  2202.     mov    cx,2[bx]
  2203.     mov    ax,ds
  2204.     mov    es,ax
  2205.     mov    di,si
  2206.     jmp    short getpro4
  2207. err_get_pro:
  2208. ;    MSG    pro_not_fnd            ; error return
  2209.     xor    ax,ax
  2210.     mov    es,ax 
  2211.     mov    di,ax
  2212. getpro4:
  2213.     pop    si                ; common return
  2214.     pop    bx
  2215.     pop    ds
  2216.     pop    bp
  2217.     ret    10
  2218. get_pro    ENDP
  2219.  
  2220.  
  2221. pkt_ptr    PROC    NEAR                ; Set up pointers in Packet 
  2222.     mov    ax,cs                ; Driver ldt and cct
  2223.     mov    ds,ax                ;  Note:most of the could 
  2224.     mov    bx,offset drv_ldt        ;  (should) be done statically
  2225.     mov    word ptr [bx],offset drv_cct    ; driver's cct back pointer
  2226.     mov    2[bx], ax
  2227.     add    bx,8                ; skip int flgs
  2228.     mov    [bx],offset req_con        ; RequestConfirm address
  2229.     mov    2[bx],ax
  2230.     mov    4[bx],offset xmt_con        ; TransmitConfirm address
  2231.     mov    6[bx],ax
  2232.     mov    8[bx],offset rcv_lah        ; ReceiveLookahead indication 
  2233.     mov    10[bx],ax
  2234.     mov    12[bx],offset ind_com        ; IndicationComplete address
  2235.     mov    14[bx],ax
  2236.     mov    16[bx],offset rcv_chn        ; ReceiveChain indication add
  2237.     mov    18[bx],ax
  2238.     mov    20[bx],offset sta_ind        ; status indication address
  2239.     mov    22[bx],ax
  2240.  
  2241.     mov    bx,offset drv_cct.ldtp        ; set up point to drv ldt
  2242.     mov    word ptr [bx],offset drv_ldt
  2243.     mov    2[bx],ax
  2244. ;
  2245. ;set up pointers in pkt driver cct
  2246. ;    only doing lower dispatch table, all other left NULL
  2247. ;    hopefully this will work
  2248. ;
  2249.     mov    drv_cct.mod_id,-1
  2250.     mov    drv_cct.mod_ds,ax
  2251.     mov    bx,offset drv_cct.system
  2252.     mov    [bx],offset dis_pat        ; drv system func entry point
  2253.     mov    2[bx],ax            ; drv ds
  2254.     mov    word ptr 16[bx],offset drv_ldt    ; ptr to ldt
  2255.     mov    18[bx],ax
  2256.     ret
  2257. pkt_ptr    ENDP
  2258.  
  2259. ; Text messages that can be flushed after startup but before bind.
  2260.  
  2261. msg_no_vect    db    "Vector not specified", EOL
  2262. msg_bad_vec    db    "Invalid vector (must be 60h-7Fh)",EOL
  2263. msg_err_clo    db    "Error closing MAC driver", EOL
  2264. msg_copyright    db     "MAC/DIS to Packet Driver converter loaded."
  2265.         db    " Version 1.09",CR,LF
  2266.         db     "Copyright 1991 FTP Software, Inc.  All rights "
  2267.         db    "reserved.", cr,lf
  2268.         db    " v1.07 by Joe R. Doupnik, jrd@cc.usu.edu, "
  2269.         db    "Utah State Univ, 18 May 1991", cr,lf
  2270.         db    " v1.08 by Dan Lanciani, ddl@harvard.harvard.edu",cr,lf
  2271.         db    " v1.09 by Joe R. Doupnik, jrd@cc.usu.edu, "
  2272.         db    "Utah State Univ, 3 Nov 1991",EOL
  2273. pm__nam        db    "protman$", 0
  2274. pro_no_open    db    "Protocol Manager not present", EOL
  2275. pro_bad_gpm    db    "GetProtocolManagerInfo call failed", EOL
  2276. pro_nam        db    "PKTDRV",0
  2277. pro_nam_len    equ    $ - pro_nam
  2278. pro_prm_vec    db    "INTVEC",0
  2279. pro_prm_vec_len    equ    $ - pro_prm_vec 
  2280. pro_daisy_vec    db    "CHAINVEC",0
  2281. pro_daisy_len    equ    $ - pro_daisy_vec 
  2282. pro_prm_nok    db    "SINTVECXX",0
  2283. pro_prm_nok_len    equ    $ - pro_prm_nok
  2284. pro_bnd_to    db    "BINDINGS",0
  2285. pro_bnd_to_len    equ    $ - pro_bnd_to
  2286. pro_novell    db    "NOVELL",0
  2287. pro_nov_len    equ    $ - pro_novell
  2288. novmsg        db    "Using OLD NOVELL 802.3 packets on the wire",EOL
  2289. vec_not_spc    db    "Interrupt vector for Packet Driver not specifed"
  2290.         db    " in PROTOCOL.INI", EOL
  2291. reg_mod_nok    db    "Register module call failed", EOL
  2292. CSEG    ends
  2293.     end
  2294.